From 73eea4eee65f7ee7912a17673042e3d6bf781f84 Mon Sep 17 00:00:00 2001 From: jilles Date: Sun, 1 Sep 2013 19:59:54 +0000 Subject: system(): Restore behaviour for SIGINT and SIGQUIT. As mentioned in r16117 and the book "Advanced Programming in the Unix Environment" by W. Richard Stevens, we should ignore SIGINT and SIGQUIT before forking, since it is not guaranteed that the parent process starts running soon enough. To avoid calling sigaction() in the vforked child, instead block SIGINT and SIGQUIT before vfork() and keep the sigaction() to ignore after vfork(). The FreeBSD kernel discards ignored signals, even if they are blocked; therefore, it is not necessary to unblock SIGINT and SIGQUIT earlier. --- lib/libc/stdlib/system.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/libc') diff --git a/lib/libc/stdlib/system.c b/lib/libc/stdlib/system.c index 64a5447..e018e6f 100644 --- a/lib/libc/stdlib/system.c +++ b/lib/libc/stdlib/system.c @@ -59,6 +59,8 @@ __system(const char *command) (void)sigemptyset(&newsigblock); (void)sigaddset(&newsigblock, SIGCHLD); + (void)sigaddset(&newsigblock, SIGINT); + (void)sigaddset(&newsigblock, SIGQUIT); (void)_sigprocmask(SIG_BLOCK, &newsigblock, &oldsigblock); switch(pid = vfork()) { case -1: /* error */ -- cgit v1.1 From e6c5cc6ac3c71369ec8c5d232929a3aa50ba1004 Mon Sep 17 00:00:00 2001 From: rwatson Date: Tue, 3 Sep 2013 08:19:06 +0000 Subject: Document SIGLIBRT in signal(3); take a stab at the signal description as the original committer didn't provide one. MFC after: 3 days --- lib/libc/gen/signal.3 | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/libc') diff --git a/lib/libc/gen/signal.3 b/lib/libc/gen/signal.3 index a41d258..ea6df44 100644 --- a/lib/libc/gen/signal.3 +++ b/lib/libc/gen/signal.3 @@ -132,6 +132,7 @@ is possible on a descriptor (see .It 30 Ta Dv SIGUSR1 Ta "terminate process" Ta "User defined signal 1" .It 31 Ta Dv SIGUSR2 Ta "terminate process" Ta "User defined signal 2" .It 32 Ta Dv SIGTHR Ta "terminate process" Ta "thread interrupt" +.It 33 Ta Dv SIGLIBRT Ta "terminate process" Ta "real-time library interrupt" .El .Pp The -- cgit v1.1 From 029a6f5d92dc57925b5f155d94d6e01fdab7a45d Mon Sep 17 00:00:00 2001 From: pjd Date: Thu, 5 Sep 2013 00:09:56 +0000 Subject: Change the cap_rights_t type from uint64_t to a structure that we can extend in the future in a backward compatible (API and ABI) way. The cap_rights_t represents capability rights. We used to use one bit to represent one right, but we are running out of spare bits. Currently the new structure provides place for 114 rights (so 50 more than the previous cap_rights_t), but it is possible to grow the structure to hold at least 285 rights, although we can make it even larger if 285 rights won't be enough. The structure definition looks like this: struct cap_rights { uint64_t cr_rights[CAP_RIGHTS_VERSION + 2]; }; The initial CAP_RIGHTS_VERSION is 0. The top two bits in the first element of the cr_rights[] array contain total number of elements in the array - 2. This means if those two bits are equal to 0, we have 2 array elements. The top two bits in all remaining array elements should be 0. The next five bits in all array elements contain array index. Only one bit is used and bit position in this five-bits range defines array index. This means there can be at most five array elements in the future. To define new right the CAPRIGHT() macro must be used. The macro takes two arguments - an array index and a bit to set, eg. #define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL) We still support aliases that combine few rights, but the rights have to belong to the same array element, eg: #define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL) #define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL) #define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP) There is new API to manage the new cap_rights_t structure: cap_rights_t *cap_rights_init(cap_rights_t *rights, ...); void cap_rights_set(cap_rights_t *rights, ...); void cap_rights_clear(cap_rights_t *rights, ...); bool cap_rights_is_set(const cap_rights_t *rights, ...); bool cap_rights_is_valid(const cap_rights_t *rights); void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src); void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src); bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little); Capability rights to the cap_rights_init(), cap_rights_set(), cap_rights_clear() and cap_rights_is_set() functions are provided by separating them with commas, eg: cap_rights_t rights; cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_FSTAT); There is no need to terminate the list of rights, as those functions are actually macros that take care of the termination, eg: #define cap_rights_set(rights, ...) \ __cap_rights_set((rights), __VA_ARGS__, 0ULL) void __cap_rights_set(cap_rights_t *rights, ...); Thanks to using one bit as an array index we can assert in those functions that there are no two rights belonging to different array elements provided together. For example this is illegal and will be detected, because CAP_LOOKUP belongs to element 0 and CAP_PDKILL to element 1: cap_rights_init(&rights, CAP_LOOKUP | CAP_PDKILL); Providing several rights that belongs to the same array's element this way is correct, but is not advised. It should only be used for aliases definition. This commit also breaks compatibility with some existing Capsicum system calls, but I see no other way to do that. This should be fine as Capsicum is still experimental and this change is not going to 9.x. Sponsored by: The FreeBSD Foundation --- lib/libc/Makefile | 1 + lib/libc/capability/Makefile.inc | 19 +++++++++++++++++++ lib/libc/capability/Symbol.map | 14 ++++++++++++++ lib/libc/include/compat.h | 2 -- lib/libc/sys/Symbol.map | 3 +-- 5 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 lib/libc/capability/Makefile.inc create mode 100644 lib/libc/capability/Symbol.map (limited to 'lib/libc') diff --git a/lib/libc/Makefile b/lib/libc/Makefile index cf2d2aa..2806cc7 100644 --- a/lib/libc/Makefile +++ b/lib/libc/Makefile @@ -100,6 +100,7 @@ NOASM= CFLAGS+= -DYP .include "${.CURDIR}/yp/Makefile.inc" .endif +.include "${.CURDIR}/capability/Makefile.inc" .if ${MK_HESIOD} != "no" CFLAGS+= -DHESIOD .endif diff --git a/lib/libc/capability/Makefile.inc b/lib/libc/capability/Makefile.inc new file mode 100644 index 0000000..934fc8b --- /dev/null +++ b/lib/libc/capability/Makefile.inc @@ -0,0 +1,19 @@ +# $FreeBSD$ + +# capability sources +.PATH: ${.CURDIR}/../../sys/kern + +SRCS+= subr_capability.c + +SYM_MAPS+= ${.CURDIR}/capability/Symbol.map + +#MAN+= cap_rights_init.3 + +#MLINKS+=cap_rights_init.3 cap_rights_set.3 +#MLINKS+=cap_rights_init.3 cap_rights_clear.3 +#MLINKS+=cap_rights_init.3 cap_rights_is_set.3 +#MLINKS+=cap_rights_init.3 cap_rights_is_valid.3 +#MLINKS+=cap_rights_init.3 cap_rights_merge.3 +#MLINKS+=cap_rights_init.3 cap_rights_remove.3 +#MLINKS+=cap_rights_init.3 cap_rights_contains.3 + diff --git a/lib/libc/capability/Symbol.map b/lib/libc/capability/Symbol.map new file mode 100644 index 0000000..c5c18c2 --- /dev/null +++ b/lib/libc/capability/Symbol.map @@ -0,0 +1,14 @@ +/* + * $FreeBSD$ + */ + +FBSD_1.3 { + __cap_rights_clear; + cap_rights_contains; + __cap_rights_init; + __cap_rights_is_set; + cap_rights_is_valid; + cap_rights_merge; + cap_rights_remove; + __cap_rights_set; +}; diff --git a/lib/libc/include/compat.h b/lib/libc/include/compat.h index 3739fe1..7694540 100644 --- a/lib/libc/include/compat.h +++ b/lib/libc/include/compat.h @@ -42,8 +42,6 @@ __sym_compat(__semctl, freebsd7___semctl, FBSD_1.0); __sym_compat(msgctl, freebsd7_msgctl, FBSD_1.0); __sym_compat(shmctl, freebsd7_shmctl, FBSD_1.0); -__sym_compat(cap_getrights, cap_rights_get, FBSD_1.2); - #undef __sym_compat #endif /* __LIBC_COMPAT_H__ */ diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map index 4f1104e..222f5f0 100644 --- a/lib/libc/sys/Symbol.map +++ b/lib/libc/sys/Symbol.map @@ -363,7 +363,6 @@ FBSD_1.1 { FBSD_1.2 { cap_enter; cap_getmode; - cap_new; getloginclass; pdfork; pdgetpid; @@ -385,7 +384,7 @@ FBSD_1.3 { cap_fcntls_limit; cap_ioctls_get; cap_ioctls_limit; - cap_rights_get; + __cap_rights_get; cap_rights_limit; cap_sandboxed; chflagsat; -- cgit v1.1 From 178dd060a80512b07630eb7f22500ed9871ca84c Mon Sep 17 00:00:00 2001 From: jilles Date: Fri, 6 Sep 2013 09:08:40 +0000 Subject: Update some signal man pages for multithreading. --- lib/libc/sys/sigaction.2 | 52 +++++++++++++++++++++++++++++++---------------- lib/libc/sys/sigpending.2 | 4 ++-- lib/libc/sys/sigreturn.2 | 6 +++--- lib/libc/sys/sigwait.2 | 4 ++-- 4 files changed, 41 insertions(+), 25 deletions(-) (limited to 'lib/libc') diff --git a/lib/libc/sys/sigaction.2 b/lib/libc/sys/sigaction.2 index d975ef9..5c784f6 100644 --- a/lib/libc/sys/sigaction.2 +++ b/lib/libc/sys/sigaction.2 @@ -28,7 +28,7 @@ .\" From: @(#)sigaction.2 8.2 (Berkeley) 4/3/94 .\" $FreeBSD$ .\" -.Dd June 8, 2013 +.Dd September 6, 2013 .Dt SIGACTION 2 .Os .Sh NAME @@ -55,7 +55,7 @@ struct sigaction { .Sh DESCRIPTION The system defines a set of signals that may be delivered to a process. Signal delivery resembles the occurrence of a hardware interrupt: -the signal is normally blocked from further occurrence, the current process +the signal is normally blocked from further occurrence, the current thread context is saved, and a new one is built. A process may specify a .Em handler @@ -64,13 +64,14 @@ to which a signal is delivered, or specify that a signal is to be A process may also specify that a default action is to be taken by the system when a signal occurs. A signal may also be -.Em blocked , -in which case its delivery is postponed until it is +.Em blocked +for a thread, +in which case it will not be delivered to that thread until it is .Em unblocked . The action to be taken on delivery is determined at the time of delivery. Normally, signal handlers execute on the current stack -of the process. +of the thread. This may be changed, on a per-handler basis, so that signals are taken on a special .Em "signal stack" . @@ -82,20 +83,30 @@ but other signals may yet occur. A global .Em "signal mask" defines the set of signals currently blocked from delivery -to a process. -The signal mask for a process is initialized +to a thread. +The signal mask for a thread is initialized from that of its parent (normally empty). It may be changed with a .Xr sigprocmask 2 -call, or when a signal is delivered to the process. +or +.Xr pthread_sigmask 3 +call, or when a signal is delivered to the thread. .Pp When a signal -condition arises for a process, the signal is added to a set of -signals pending for the process. -If the signal is not currently +condition arises for a process or thread, the signal is added to a set of +signals pending for the process or thread. +Whether the signal is directed at the process in general or at a specific +thread depends on how it is generated. +For signals directed at a specific thread, +if the signal is not currently .Em blocked -by the process then it is delivered to the process. -Signals may be delivered any time a process enters the operating system +by the thread then it is delivered to the thread. +For signals directed at the process, +if the signal is not currently +.Em blocked +by all threads then it is delivered to one thread that does not have it blocked +(the selection of which is unspecified). +Signals may be delivered any time a thread enters the operating system (e.g., during a system call, page fault or trap, or clock interrupt). If multiple signals are ready to be delivered at the same time, any signals that could be caused by traps are delivered first. @@ -106,17 +117,17 @@ The set of pending signals is returned by the .Xr sigpending 2 system call. When a caught signal -is delivered, the current state of the process is saved, +is delivered, the current state of the thread is saved, a new signal mask is calculated (as described below), and the signal handler is invoked. The call to the handler is arranged so that if the signal handling routine returns -normally the process will resume execution in the context +normally the thread will resume execution in the context from before the signal's delivery. -If the process wishes to resume in a different context, then it +If the thread wishes to resume in a different context, then it must arrange to restore the previous context itself. .Pp -When a signal is delivered to a process a new signal mask is +When a signal is delivered to a thread a new signal mask is installed for the duration of the process' signal handler (or until a .Xr sigprocmask 2 @@ -218,7 +229,7 @@ to If this bit is set, the system will deliver the signal to the process on a .Em "signal stack" , -specified with +specified by each thread with .Xr sigaltstack 2 . .It Dv SA_NODEFER If this bit is set, further occurrences of the delivered signal are @@ -272,6 +283,11 @@ However, calls that have already committed are not restarted, but instead return a partial success (for example, a short read count). .Pp After a +.Xr pthread_create 3 +the signal mask is inherited by the new thread and +the set of pending signals and the signal stack for the new thread are empty. +.Pp +After a .Xr fork 2 or .Xr vfork 2 diff --git a/lib/libc/sys/sigpending.2 b/lib/libc/sys/sigpending.2 index 37f92d8..06ecc00 100644 --- a/lib/libc/sys/sigpending.2 +++ b/lib/libc/sys/sigpending.2 @@ -31,7 +31,7 @@ .\" @(#)sigpending.2 8.3 (Berkeley) 1/12/94 .\" $FreeBSD$ .\" -.Dd January 12, 1994 +.Dd September 6, 2013 .Dt SIGPENDING 2 .Os .Sh NAME @@ -47,7 +47,7 @@ The .Fn sigpending system call returns a mask of the signals pending for delivery -to the calling process in the location indicated by +to the calling thread or the calling process in the location indicated by .Fa set . Signals may be pending because they are currently masked, or transiently before delivery (although the latter case is not diff --git a/lib/libc/sys/sigreturn.2 b/lib/libc/sys/sigreturn.2 index 13d76f6..1b76468 100644 --- a/lib/libc/sys/sigreturn.2 +++ b/lib/libc/sys/sigreturn.2 @@ -28,7 +28,7 @@ .\" @(#)sigreturn.2 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd June 4, 1993 +.Dd September 6, 2013 .Dt SIGRETURN 2 .Os .Sh NAME @@ -46,7 +46,7 @@ The system call allows users to atomically unmask, switch stacks, and return from a signal context. -The processes signal mask and stack status are +The thread's signal mask and stack status are restored from the context structure pointed to by .Fa scp . The system call does not return; @@ -65,7 +65,7 @@ is set to indicate the error. The .Fn sigreturn system call -will fail and the process context will remain unchanged +will fail and the thread context will remain unchanged if one of the following occurs. .Bl -tag -width Er .It Bq Er EFAULT diff --git a/lib/libc/sys/sigwait.2 b/lib/libc/sys/sigwait.2 index 525bffb..4da64a9 100644 --- a/lib/libc/sys/sigwait.2 +++ b/lib/libc/sys/sigwait.2 @@ -27,7 +27,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 27, 2012 +.Dd September 6, 2013 .Dt SIGWAIT 2 .Os .Sh NAME @@ -50,7 +50,7 @@ waits until one or more of the selected signals has been generated. Then .Fn sigwait atomically clears one of the selected signals from the set of pending signals -for the process and sets the location pointed to by +(for the process or for the current thread) and sets the location pointed to by .Fa sig to the signal number that was cleared. .Pp -- cgit v1.1 From c04dfb0b1932e7a84103ade5ccddab95eb4d5a28 Mon Sep 17 00:00:00 2001 From: theraven Date: Fri, 6 Sep 2013 09:46:44 +0000 Subject: Fix the namespace pollution caused by iconv.h including stdbool.h This broke any C89 ports that defined bool themselves, including things like gcc, gtk, and so on. --- lib/libc/iconv/citrus_iconv_local.h | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/libc') diff --git a/lib/libc/iconv/citrus_iconv_local.h b/lib/libc/iconv/citrus_iconv_local.h index 52ac825..e673c9a 100644 --- a/lib/libc/iconv/citrus_iconv_local.h +++ b/lib/libc/iconv/citrus_iconv_local.h @@ -31,6 +31,7 @@ #define _CITRUS_ICONV_LOCAL_H_ #include +#include #define _CITRUS_ICONV_GETOPS_FUNC_BASE(_n_) \ int _n_(struct _citrus_iconv_ops *) -- cgit v1.1 From 68907dc5984d1396b8cd4013146c968206aeb2ad Mon Sep 17 00:00:00 2001 From: jilles Date: Fri, 6 Sep 2013 13:47:16 +0000 Subject: libc/stdio: Allow fopen/freopen modes in any order (except initial r/w/a). Austin Group issue #411 requires 'e' to be accepted before and after 'x', and encourages accepting the characters in any order, except the initial 'r', 'w' or 'a'. Given that glibc accepts the characters after r/w/a in any order and that diagnosing this problem may be hard, change our libc to behave that way as well. --- lib/libc/stdio/flags.c | 55 +++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 27 deletions(-) (limited to 'lib/libc') diff --git a/lib/libc/stdio/flags.c b/lib/libc/stdio/flags.c index 1878c2f..b7552a4 100644 --- a/lib/libc/stdio/flags.c +++ b/lib/libc/stdio/flags.c @@ -51,7 +51,7 @@ __FBSDID("$FreeBSD$"); int __sflags(const char *mode, int *optr) { - int ret, m, o; + int ret, m, o, known; switch (*mode++) { @@ -78,34 +78,35 @@ __sflags(const char *mode, int *optr) return (0); } - /* 'b' (binary) is ignored */ - if (*mode == 'b') - mode++; - - /* [rwa][b]\+ means read and write */ - if (*mode == '+') { - mode++; - ret = __SRW; - m = O_RDWR; - } - - /* 'b' (binary) can appear here, too -- and is ignored again */ - if (*mode == 'b') - mode++; - - /* 'x' means exclusive (fail if the file exists) */ - if (*mode == 'x') { - mode++; - if (m == O_RDONLY) { - errno = EINVAL; - return (0); + do { + known = 1; + switch (*mode++) { + case 'b': + /* 'b' (binary) is ignored */ + break; + case '+': + /* [rwa][b]\+ means read and write */ + ret = __SRW; + m = O_RDWR; + break; + case 'x': + /* 'x' means exclusive (fail if the file exists) */ + o |= O_EXCL; + break; + case 'e': + /* set close-on-exec */ + o |= O_CLOEXEC; + break; + default: + known = 0; + break; } - o |= O_EXCL; - } + } while (known); - /* set close-on-exec */ - if (*mode == 'e') - o |= O_CLOEXEC; + if ((o & O_EXCL) != 0 && m == O_RDONLY) { + errno = EINVAL; + return (0); + } *optr = m | o; return (ret); -- cgit v1.1