version 1.14, 1998/12/07 23:06:48 |
version 1.15, 1998/12/20 17:08:45 |
|
|
<html> |
<html> |
<head> |
<head> |
<meta http-equiv="Content-Type" |
<meta http-equiv="Content-Type" |
content="text/html; charset=iso-8859-1"> |
content="text/html; charset=iso-8859-1"> |
<meta name="resource-type" |
<meta name="resource-type" |
content="document"> |
content="document"> |
<meta name="description" |
<meta name="description" |
CONTENT="How to make an OpenBSD port"> |
CONTENT="How to make an OpenBSD port"> |
<meta name="keywords" |
<meta name="keywords" |
content="openbsd,ports"> |
content="openbsd,ports"> |
<meta name="distribution" |
<meta name="distribution" |
content="global"> |
content="global"> |
<meta name="copyright" |
<meta name="copyright" |
content="This document copyright 1997 by the OpenBSD project"> |
content="This document copyright 1997 by the OpenBSD project"> |
<title>Building an OpenBSD port</title> |
<title>Building an OpenBSD port</title> |
<link rev="made" HREF="mailto:www@openbsd.org"> |
<link rev="made" HREF="mailto:www@openbsd.org"> |
</head> |
</head> |
|
|
<a href="http://www.freebsd.org/handbook/porting.html">FreeBSD |
<a href="http://www.freebsd.org/handbook/porting.html">FreeBSD |
Handbook</a>. This is the FreeBSD porting bible. |
Handbook</a>. This is the FreeBSD porting bible. |
<li>OpenBSD porting <a href="checklist.html">checklist</a>. |
<li>OpenBSD porting <a href="checklist.html">checklist</a>. |
<li><a href="audio-port.html">Porting audio applications to OpenBSD</a>. |
<li><a href="audio-port.html">Porting audio applications to OpenBSD</a>. |
<li>The OpenBSD ports mailing list, |
<li>The OpenBSD ports mailing list, |
<a href="mailto:ports@openbsd.org">ports@OpenBSD.ORG</a>. |
<a href="mailto:ports@openbsd.org">ports@OpenBSD.ORG</a>. |
</ul> |
</ul> |
|
|
<ul> |
<ul> |
<li>OpenBSD does NOT use /usr/local/etc/rc.d.<br> |
<li>OpenBSD does NOT use /usr/local/etc/rc.d.<br> |
<code>/usr/local</code> is often shared between several machines |
<code>/usr/local</code> is often shared between several machines |
thanks to NFS. For this reason, configuration files that are specific |
thanks to NFS. For this reason, configuration files that are specific |
to a given machine can't be stored under <code>/usr/local</code>, |
to a given machine can't be stored under <code>/usr/local</code>, |
<code>/etc</code> is the central repository for per machine |
<code>/etc</code> is the central repository for per machine |
configuration files. Moreover, OpenBSD policy is to never update |
configuration files. Moreover, OpenBSD policy is to never update |
files under <code>/etc</code> automatically. Ports that need some |
files under <code>/etc</code> automatically. Ports that need some |
specific boot setup should advise the administrator about what to do |
specific boot setup should advise the administrator about what to do |
instead of blindly installing files. |
instead of blindly installing files. |
<li>OpenBSD does NOT compress man pages. |
<li>OpenBSD does NOT compress man pages. |
<li>OpenBSD does NOT require <code>-lcrypt</code>.<br> |
<li>OpenBSD does NOT require <code>-lcrypt</code>.<br> |
DES encryption is part of the standard <code>libc</code>. |
DES encryption is part of the standard <code>libc</code>. |
|
|
conditions where you don't have proper control. For instance, an attacker |
conditions where you don't have proper control. For instance, an attacker |
who already has user privileges on your machines may replace files in |
who already has user privileges on your machines may replace files in |
<code>/tmp</code> with symbolic links to more strategic files, such as |
<code>/tmp</code> with symbolic links to more strategic files, such as |
<code>/etc/passwd</code>. For instance, the bsd linker warns about |
<code>/etc/passwd</code>. |
<code>mktemp</code> uses. <strong>These must be fixed</strong>. |
|
This is not quite as simple as <code>s/mktemp/mkstemp/g</code>. |
<li>For instance, one very common problem is the <code>mktemp</code> |
|
function. Head the warnings of the bsd linker about its uses. |
|
<strong>These must be fixed</strong>. |
|
This is not quite as simple as <code>s/mktemp/mkstemp/g</code>. <br> |
|
Refer to the <code>mktemp(3)</code> man page of OpenBSD current |
|
for more indications. |
|
Correct code using <code>mkstemp</code> includes the source to |
|
<code>ed</code> or <code>mail</code>. |
|
A rare instance of code that uses <code>mktemp</code> correctly |
|
can be found in the <code>rsync</code> port. |
|
|
<li>Just because you can read it doesn't mean you should. A well-known hole |
<li>Just because you can read it doesn't mean you should. A well-known hole |
of this nature was the <code>startx</code> problem. As a setuid program, |
of this nature was the <code>startx</code> problem. As a setuid program, |
|
|
Pretty handy to grab the first line of a shadow passwd file, considering |
Pretty handy to grab the first line of a shadow passwd file, considering |
these often start with root entry. Do not open your file, and then do |
these often start with root entry. Do not open your file, and then do |
an <code>fstat</code> on the open descriptor to check if you should have |
an <code>fstat</code> on the open descriptor to check if you should have |
been able to open it (or the attacked will play with /dev/rst0 and rewind |
been able to open it (or the attacker will play with /dev/rst0 and rewind |
your tape) -- open it with the correct uid/gid/grouplist set. |
your tape) -- open it with the correct uid/gid/grouplist set. |
|
|
<li>Don't use anything that forks a shell in setuid programs before dropping |
<li>Don't use anything that forks a shell in setuid programs before dropping |
your privileges. This includes <code>popen</code> and <code>system</code>. |
your privileges. This includes <code>popen</code> and |
|
<code>system</code>. |
Use <code>fork</code>, <code>pipe</code> and <code>execve</code> instead. |
Use <code>fork</code>, <code>pipe</code> and <code>execve</code> instead. |
|
|
<li>Pass open descriptors instead of filenames to other programs to avoid race |
<li>Pass open descriptors instead of filenames to other programs to |
conditions. Even if a program does not accept file descriptors, you can |
avoid race conditions. Even if a program does not accept file |
still use <code>/dev/fd/0</code>. |
descriptors, you can still use <code>/dev/fd/0</code>. |
|
|
<li>Access rights are attached to file descriptors. If you need setuid rights |
<li>Access rights are attached to file descriptors. If you need setuid rights |
to open a file, open that file, then drop your privileges. You can still |
to open a file, open that file, then drop your privileges. You can still |
access the open descriptor, but you have less to worry about. This is |
access the open descriptor, but you have less to worry about. This is |
double-edged: even after dropping privileges, you should still watch out |
double-edged: even after dropping privileges, you should still watch out |
for those descriptors. |
for those descriptors. |
|
|
<li>Avoid root setuid as much as you can. Basically, root can do anything, |
<li>Avoid root setuid as much as you can. Basically, root can do anything, |
but root rights are very rarely needed, except maybe to create socket ports with |
but root rights are very rarely needed, except maybe to create |
a number under 1024. It is arguably better to keep that under <code>inetd</code> |
socket ports with a number under 1024. It is arguably better to |
|
keep that under <code>inetd</code> |
control and just add the relevant entries to <code>inetd.conf</code>. |
control and just add the relevant entries to <code>inetd.conf</code>. |
You must know the appropriate magic for writing daemons to achieve that. |
You must know the appropriate magic for writing daemons to achieve that. |
It could be argued that you have no business writing setuid programs if you don't |
It could be argued that you have no business writing setuid programs |
know how to do that. |
if you don't know how to do that. |
|
|
<li>Use setgid instead of setuid. Apart from those specific files needed by setgid |
<li>Use setgid instead of setuid. Apart from those specific files needed |
programs, most files are not group-writable. Hence, a security problem in a setgid |
by setgid programs, most files are not group-writable. Hence, a |
program won't compromise your system as much: with only group rights, the worst |
security problem in a setgid program won't compromise your system as |
an intruder will be able to do is hack a games score table or some such. |
much: with only group rights, the worst an intruder will be able to |
|
do is hack a games score table or some such. |
See the <code>xkobo</code> port for an instance of such a change. |
See the <code>xkobo</code> port for an instance of such a change. |
|
|
<li>Don't trust group-writable files. Even though they are audited, setgid programs |
<li>Don't trust group-writable files. Even though they are audited, |
are not perceived as important potential security holes. Hence stuff they can tamper |
setgid programs are not perceived as important potential security |
with shouldn't be considered sensitive information. |
holes. Hence stuff they can tamper with shouldn't be considered |
|
sensitive information. |
|
|
<li>Don't trust your environment ! This involves simple things such as your <code>PATH</code> |
<li>Don't trust your environment ! This involves simple things such as |
(never use <code>system</code> with an unqualified name), but also more subtle items |
your <code>PATH</code> (never use <code>system</code> with an |
such as your locale, timezone, termcap, and so on. Be aware of transitivity: even though you're |
unqualified name, avoid <code>execvp</code>), but also more subtle |
taking full precautions, programs you call directly won't necessarily. <strong>Never</strong> |
items such as your locale, timezone, termcap, and so on. |
use <code>system</code> in privileged programs, build your command line, a controlled environment, |
Be aware of transitivity: even though you're taking full precautions, |
and call <code>execvp</code> directly. The <code>perlsec</code> man page is a good tutorial on |
programs you call directly won't necessarily. <strong>Never</strong> |
such problems. |
use <code>system</code> in privileged programs, build your command |
|
line, a controlled environment, and call <code>execve</code> directly. |
|
The <code>perlsec</code> man page is a good tutorial on such problems. |
|
|
<li>Never used setuid shell-scripts. These are inherently insecure. Wrap them into some C code |
<li>Never used setuid shell-scripts. These are inherently insecure. |
that ensures a proper environment. On the other hand, OpenBSD features secure perl scripts. |
Wrap them into some C code that ensures a proper environment. |
|
On the other hand, OpenBSD features secure perl scripts. |
|
|
<li>Beware the dynamic loader. If you are running setuid, it will only use trusted libraries |
<li>Beware the dynamic loader. If you are running setuid, it will only |
that were scanned with ldconfig. Setgid is not enough. |
use trusted libraries that were scanned with ldconfig. |
|
Setgid is not enough. |
|
|
<li>Dynamic libraries are tricky. C++ code sets a similar problem. Basically, libraries may take |
<li>Dynamic libraries are tricky. C++ code sets a similar problem. |
some action based upon your environment before your main program even gets to check its setuid |
Basically, libraries may take some action based upon your environment |
status. OpenBSD <code>issetugid</code> addresses this problem, from the library writer point |
before your main program even gets to check its setuid status. |
of view. Don't try to port libraries unless you understand this issue thoroughly. |
OpenBSD <code>issetugid</code> addresses this problem, from the |
|
library writer point of view. Don't try to port libraries unless you |
|
understand this issue thoroughly. |
</ul> |
</ul> |
<h3><font color=#0000e0>Generic porting hints</font></h3> |
<h3><font color=#0000e0>Generic porting hints</font></h3> |
<ul> |
<ul> |
|
|
#endif |
#endif |
</pre> |
</pre> |
<li>Test for features, not for specific OSes. In the long run, it is much |
<li>Test for features, not for specific OSes. In the long run, it is much |
better to test whether <code>tcgetattr</code> works than whether you're running |
better to test whether <code>tcgetattr</code> works than whether |
under BSD 4.3 or later, or SystemVR4. These kind of tests just confuse the |
you're running under BSD 4.3 or later, or SystemVR4. These kind of |
issue. The way to go about it is, for instance, to test for one particular |
tests just confuse the issue. The way to go about it is, for instance, |
system, set up a slew of <code>HAVE_TCGETATTR</code> defines, then proceed to |
to test for one particular system, set up a slew of |
the next system. This technique separates features tests from specific OSes. |
<code>HAVE_TCGETATTR</code> defines, then proceed to the next system. |
In a hurry, another porter can just add the whole set of <code>-DHAVE_XXX</code> |
This technique separates features tests from specific OSes. |
defines to the Makefile. One may also write or add to a configure script to check for |
In a hurry, another porter can just add the whole set of |
that feature and add it automatically. As an example not to follow, check nethack 3.2.2 |
<code>-DHAVE_XXX</code> defines to the Makefile. One may also write |
source: it assumes loads of things based on the system type. Most of these assumptions |
or add to a configure script to check for that feature and add it |
are obsolete and no longer reflect reality: POSIX functions are more useful than older |
automatically. As an example not to follow, check nethack 3.2.2 |
BSD versus SystemV differences, to the point that some traditional bsd functions are |
source: it assumes loads of things based on the system type. Most |
|
of these assumptions are obsolete and no longer reflect reality: |
|
POSIX functions are more useful than older BSD versus SystemV |
|
differences, to the point that some traditional bsd functions are |
now only supported through compatibility libraries. |
now only supported through compatibility libraries. |
|
|
<li>Avoid include files that include other includes that... First, because |
<li>Avoid include files that include other includes that... First, because |
this is inefficient. Your project will end up including a file that includes |
this is inefficient. Your project will end up including a file that |
everything. Also, because it makes some problems difficult to correct. It |
includes everything. Also, because it makes some problems difficult |
becomes harder to <em>not</em> include one particular file at a given point. |
to fix. It becomes harder to <em>not</em> include one particular file |
|
at a given point. |
|
|
<li>Avoid bizarre macro tricks. Undefining a macro that was defined by a |
<li>Avoid bizarre macro tricks. Undefining a macro that was defined by a |
header file is a bad idea. Defining macros to get some specific behavior |
header file is a bad idea. Defining macros to get some specific behavior |
from an include file is also a bad idea: compilation modes should be global. |
from an include file is also a bad idea: compilation modes should be |
If you want POSIX behavior, say so, and <code>#define POSIX_C_SOURCE</code> |
global. If you want POSIX behavior, say so, and |
|
<code>#define POSIX_C_SOURCE</code> |
throughout the whole project, not when you feel like it. |
throughout the whole project, not when you feel like it. |
|
|
<li>Don't ever write system function prototypes. All modern systems, |
<li>Don't ever write system function prototypes. All modern systems, |
OpenBSD included, have a standard location for these prototypes. Likely |
OpenBSD included, have a standard location for these prototypes. Likely |
places include <code>unistd.h</code>, <code>fcntl.h</code> or <code>termios.h</code>. |
places include <code>unistd.h</code>, <code>fcntl.h</code> or |
The man page frequently states where the prototype lies. You might need |
<code>termios.h</code>. |
another slew of <code>HAVE_XXX</code> macros to procure the right file. |
The man page frequently states where the prototype can be found. |
Don't worry about including the same file twice, include files have guards |
You might need another slew of <code>HAVE_XXX</code> macros to |
that prevent all kinds of nastiness.<br> |
procure the right file. Don't worry about including the same file |
|
twice, include files have guards that prevent all kinds of nastiness.<br> |
If some broken system needs you to write the prototype, don't impose |
If some broken system needs you to write the prototype, don't impose |
on all other systems. Roll-your-own prototypes will break because they may |
on all other systems. Roll-your-own prototypes will break because they |
use types that are equivalent on your system, but are not portable to other |
may use types that are equivalent on your system, but are not portable |
systems (<code>unsigned long</code> instead of <code>size_t</code>), or get some |
to other systems (<code>unsigned long</code> instead of |
<code>const</code> status wrong. Also, some compilers, such as OpenBSD's own gcc, |
<code>size_t</code>), or get some <code>const</code> status wrong. |
|
Also, some compilers, such as OpenBSD's own gcc, |
are able to do a better job with some very frequent functions such as |
are able to do a better job with some very frequent functions such as |
<code>strlen</code> if you include the right header file. |
<code>strlen</code> if you include the right header file. |
|
|
<li>Don't use the name of a standard system function for anything else. |
<li>Don't use the name of a standard system function for anything else. |
If you want to write your own function, give it its own name, and call that |
If you want to write your own function, give it its own name, and |
function everywhere. If you wish to revert to the default system function, |
call that function everywhere. If you wish to revert to the |
you just need to comment your code out, and define your own name to the |
default system function, you just need to comment your code out, |
system function. Don't do it the other way round. Code should look like this |
and define your own name to the system function. Don't do it the |
|
other way round. Code should look like this |
<pre> |
<pre> |
/* prototype part */ |
/* prototype part */ |
#ifdef USE_OWN_GCVT |
#ifdef USE_OWN_GCVT |
|
|
#ifdef USE_OWN_GCVT |
#ifdef USE_OWN_GCVT |
char *foo_gcvt(double number, size_t ndigit, char *buf) |
char *foo_gcvt(double number, size_t ndigit, char *buf) |
{ |
{ |
/* proper definition */ |
/* proper definition */ |
} |
} |
|
|
/* typical use */ |
/* typical use */ |
s = foo_gcvt(n, 15, b); |
s = foo_gcvt(n, 15, b); |
|
|
</ul> |
</ul> |
<h3><font color=#0000e0>Other Helpful Hints</font></h3> |
<h3><font color=#0000e0>Other Helpful Hints</font></h3> |
<ul> |
<ul> |
<li>Do not assume <code>/usr/local/bin</code> or |
<li>Recent versions of <code>bsd.port.mk</code> set the installers |
<code>/usr/X11R6/bin</code> is in the installers path. A good |
path. Specifically, they set <code>/usr/bin</code> and |
way to verify this is to create and install your port while |
<code>/bin</code> to be searched <em>before</em> |
running as <code>root</code> with only <code>/bin</code> and |
<code>/usr/local/bin</code> and <code>/usr/X11R6/bin</code>. |
<code>/usr/bin</code> in your path. |
<li>Do <em>NOT</em> generate shared libraries for <code>${MACHINE_ARCH} == |
<li>Do NOT generate shared libraries for <code>${MACHINE_ARCH} == |
|
alpha</code> |
alpha</code> |
<li>In OpenBSD <code>curses.h/libcurses/libtermlib</code> are the |
<li>In OpenBSD <code>curses.h/libcurses/libtermlib</code> are the |
``new curses''. Change:<br> |
``new curses''. Change:<br> |
<code>ncurses.h ==> curses.h</code><br> |
<code>ncurses.h ==> curses.h</code><br> |
<code>-lncurses ==> -lcurses</code><br> |
<code>-lncurses ==> -lcurses</code><br> |
``old (BSD) curses'' is available by defining <code>_USE_OLD_CURSES_</code> |
``old (BSD) curses'' is available by defining |
|
<code>_USE_OLD_CURSES_</code> |
before including <code>curses.h</code> (usually in a Makefile) and |
before including <code>curses.h</code> (usually in a Makefile) and |
linking with <code>-lcurses</code>. |
linking with <code>-locurses</code>. |
<li>In OpenBSD, terminal discipline has been upgraded from the older BSD |
<li>In OpenBSD, terminal discipline has been upgraded from the older BSD |
<code>sgtty</code> to the newer POSIX <code>tcgetattr</code> family. |
<code>sgtty</code> to the newer POSIX <code>tcgetattr</code> family. |
Avoid the older style in new code. Some code may define <code>tcgetattr</code> |
Avoid the older style in new code. Some code may define |
to be a synonym for the older <code>sgtty</code>, but this is at best a stopgap |
<code>tcgetattr</code> to be a synonym for the older |
measure on OpenBSD. The <code>xterm</code> source code is a very good example of |
<code>sgtty</code>, but this is at best a stopgap measure on OpenBSD. |
what not to do. |
The <code>xterm</code> source code is a very good example of |
Try to get your system functionality right: you want a type that remembers |
what not to do. Try to get your system functionality right: you |
the state of your terminal (possible typedef), you want a function that |
want a type that remembers the state of your terminal |
extracts the current state, and a function that sets the new state. |
(possible typedef), you want a function that extracts the current |
Functions that modify this state are more difficult, as they tend to vary |
state, and a function that sets the new state. |
depending upon the system. Also, don't forget that you will have to handle |
Functions that modify this state are more difficult, as they tend |
cases where you are not connected to the terminal, and that you need to |
to vary depending upon the system. Also, don't forget that you will |
handle signals: not only termination, but also getting put in the background |
have to handle cases where you are not connected to a terminal, |
you should leave your terminal in a sane state. Do your tests under an |
and that you need to handle signals: not only termination, but |
older shell, such as sh, which does not reset the terminal in any way at |
also background (<code>SIGTSTP</code>). You should always leave |
|
the terminal in a sane state. Do your tests under an older shell, |
|
such as sh, which does not reset the terminal in any way at |
program's termination. |
program's termination. |
<li>The newer termcap/terminfo and curses, as included with OpenBSD, include standard sequences |
<li>The newer termcap/terminfo and curses, as included with OpenBSD, |
for controlling color terminals. You should use these if possible, reverting |
include standard sequences for controlling color terminals. You |
to standard ANSI color sequences on other systems. However, some terminal descriptions |
should use these if possible, reverting to standard ANSI color |
have not been updated yet, and you may need to be able to specify these sequences manually. |
sequences on other systems. However, some terminal descriptions |
This is the way vim5.1 handles it. This is not strictly necessary. Except for privileged |
have not been updated yet, and you may need to be able to specify |
programs, it is generally possible to override a termcap definition through the |
these sequences manually. This is the way vim handles it. This is |
|
not strictly necessary. Except for privileged programs, it is |
|
generally possible to override a termcap definition through the |
<code>TERMCAP</code> variable and get it to work properly. |
<code>TERMCAP</code> variable and get it to work properly. |
<li>Signal semantics are tricky, and vary from one system to another. Use <code>sigaction</code> |
<li>Signal semantics are tricky, and vary from one system to another. |
to ensure a specific semantics, along with other system calls referenced in its manpage. |
Use <code>sigaction</code> to ensure a specific semantics, along |
|
with other system calls referenced in the corresponding manpage. |
</ul> |
</ul> |
<hr> |
<hr> |
<a href="index.html"><img height=24 width=24 src=back.gif border=0 alt=OpenBSD></a> |
<a href="index.html"><img height=24 width=24 src=back.gif border=0 alt=OpenBSD></a> |