summaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
authorAustin Foxley <austinf@cetoncorp.com>2009-10-17 14:25:01 -0700
committerAustin Foxley <austinf@cetoncorp.com>2009-10-17 14:25:01 -0700
commit9a737ab7a40984cfdfffd014562a220a3736a10f (patch)
tree51fe4682638ffec59b2bd41d67df82ec60d6b48d /libc
parentcfbc0081078b5a41895a2ad689627bf94eeacb43 (diff)
use *_not_cancel variants to avoid accidental cancellations with nptl
Signed-off-by: Austin Foxley <austinf@cetoncorp.com>
Diffstat (limited to 'libc')
-rw-r--r--libc/inet/hostid.c15
-rw-r--r--libc/inet/if_index.c17
-rw-r--r--libc/misc/dirent/closedir.c3
-rw-r--r--libc/misc/dirent/opendir.c10
-rw-r--r--libc/misc/utmp/utent.c13
-rw-r--r--libc/misc/utmp/wtent.c7
-rw-r--r--libc/stdio/tmpfile.c3
-rw-r--r--libc/sysdeps/linux/common/not-cancel.h19
-rw-r--r--libc/unistd/daemon.c51
9 files changed, 102 insertions, 36 deletions
diff --git a/libc/inet/hostid.c b/libc/inet/hostid.c
index 99346d7f8..c6d6204ae 100644
--- a/libc/inet/hostid.c
+++ b/libc/inet/hostid.c
@@ -14,6 +14,7 @@
#include <netdb.h>
#include <fcntl.h>
#include <unistd.h>
+#include <not-cancel.h>
#define HOSTID "/etc/hostid"
@@ -26,11 +27,11 @@ int sethostid(long int new_id)
if (geteuid() || getuid())
return __set_errno(EPERM);
- fd = open(HOSTID, O_CREAT|O_WRONLY, 0644);
+ fd = open_not_cancel(HOSTID, O_CREAT|O_WRONLY, 0644);
if (fd < 0)
return fd;
- ret = write(fd, &new_id, sizeof(new_id)) == sizeof(new_id) ? 0 : -1;
- close(fd);
+ ret = write_not_cancel(fd, &new_id, sizeof(new_id)) == sizeof(new_id) ? 0 : -1;
+ close_not_cancel_no_status (fd);
return ret;
}
#endif
@@ -44,13 +45,13 @@ long int gethostid(void)
* It is not an error if we cannot read this file. It is not even an
* error if we cannot read all the bytes, we just carry on trying...
*/
- fd = open(HOSTID, O_RDONLY);
- if (fd >= 0 && read(fd, &id, sizeof(id)))
+ fd = open_not_cancel_2(HOSTID, O_RDONLY);
+ if (fd >= 0 && read_not_cancel(fd, &id, sizeof(id)))
{
- close (fd);
+ close_not_cancel_no_status (fd);
return id;
}
- if (fd >= 0) close (fd);
+ if (fd >= 0) close_not_cancel_no_status (fd);
/* Try some methods of returning a unique 32 bit id. Clearly IP
* numbers, if on the internet, will have a unique address. If they
diff --git a/libc/inet/if_index.c b/libc/inet/if_index.c
index 750a4649e..8efcd2a76 100644
--- a/libc/inet/if_index.c
+++ b/libc/inet/if_index.c
@@ -32,6 +32,7 @@
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <libc-internal.h>
+#include <not-cancel.h>
#include "netlinkaccess.h"
@@ -55,13 +56,13 @@ if_nametoindex(const char* ifname)
{
/* close never fails here, fd is just a unconnected socket.
*int saved_errno = errno; */
- close(fd);
+ close_not_cancel_no_status(fd);
/*if (saved_errno == EINVAL)
* __set_errno(ENOSYS); */
return 0;
}
- close(fd);
+ close_not_cancel_no_status(fd);
return ifr.ifr_ifindex;
#endif
}
@@ -112,7 +113,7 @@ if_nameindex (void)
if (ioctl (fd, SIOCGIFCONF, &ifc) < 0)
{
- close (fd);
+ close_not_cancel_no_status (fd);
return NULL;
}
}
@@ -123,7 +124,7 @@ if_nameindex (void)
idx = malloc ((nifs + 1) * sizeof (struct if_nameindex));
if (idx == NULL)
{
- close(fd);
+ close_not_cancel_no_status (fd);
__set_errno(ENOBUFS);
return NULL;
}
@@ -141,7 +142,7 @@ if_nameindex (void)
for (j = 0; j < i; ++j)
free (idx[j].if_name);
free(idx);
- close(fd);
+ close_not_cancel_no_status (fd);
if (saved_errno == EINVAL)
saved_errno = ENOSYS;
else if (saved_errno == ENOMEM)
@@ -155,7 +156,7 @@ if_nameindex (void)
idx[i].if_index = 0;
idx[i].if_name = NULL;
- close(fd);
+ close_not_cancel_no_status (fd);
return idx;
#endif
}
@@ -298,14 +299,14 @@ if_indextoname (unsigned int ifindex, char *ifname)
if (ioctl (fd, SIOCGIFNAME, &ifr) < 0)
{
int serrno = errno;
- close (fd);
+ close_not_cancel_no_status (fd);
if (serrno == ENODEV)
/* POSIX requires ENXIO. */
serrno = ENXIO;
__set_errno (serrno);
return NULL;
}
- close (fd);
+ close_not_cancel_no_status (fd);
return strncpy (ifname, ifr.ifr_name, IFNAMSIZ);
# else
diff --git a/libc/misc/dirent/closedir.c b/libc/misc/dirent/closedir.c
index cca03b8f7..dfb53f888 100644
--- a/libc/misc/dirent/closedir.c
+++ b/libc/misc/dirent/closedir.c
@@ -9,6 +9,7 @@
#include <stdlib.h>
#include <unistd.h>
#include "dirstream.h"
+#include <not-cancel.h>
int closedir(DIR * dir)
@@ -31,6 +32,6 @@ int closedir(DIR * dir)
__UCLIBC_MUTEX_UNLOCK(dir->dd_lock);
free(dir->dd_buf);
free(dir);
- return close(fd);
+ return close_not_cancel(fd);
}
libc_hidden_def(closedir)
diff --git a/libc/misc/dirent/opendir.c b/libc/misc/dirent/opendir.c
index b43f60814..4a23ab061 100644
--- a/libc/misc/dirent/opendir.c
+++ b/libc/misc/dirent/opendir.c
@@ -12,6 +12,7 @@
#include <unistd.h>
#include <sys/dir.h>
#include <sys/stat.h>
+#include <not-cancel.h>
#include <dirent.h>
#include "dirstream.h"
@@ -81,7 +82,7 @@ DIR *opendir(const char *name)
}
# define O_DIRECTORY 0
#endif
- fd = open(name, O_RDONLY|O_NDELAY|O_DIRECTORY|O_CLOEXEC);
+ fd = open_not_cancel_2(name, O_RDONLY|O_NDELAY|O_DIRECTORY|O_CLOEXEC);
if (fd < 0)
return NULL;
/* Note: we should check to make sure that between the stat() and open()
@@ -93,7 +94,7 @@ DIR *opendir(const char *name)
/* this close() never fails
*int saved_errno;
*saved_errno = errno; */
- close(fd);
+ close_not_cancel_no_status(fd);
/*__set_errno(saved_errno);*/
return NULL;
}
@@ -102,12 +103,13 @@ DIR *opendir(const char *name)
* exec. From "Anna Pluzhnikov" <besp@midway.uchicago.edu>.
*/
#ifndef __ASSUME_O_CLOEXEC
- fcntl(fd, F_SETFD, FD_CLOEXEC);
+ fcntl_not_cancel(fd, F_SETFD, FD_CLOEXEC);
#endif
ptr = fd_to_DIR(fd, statbuf.st_blksize);
+
if (!ptr) {
- close(fd);
+ close_not_cancel_no_status(fd);
__set_errno(ENOMEM);
}
return ptr;
diff --git a/libc/misc/utmp/utent.c b/libc/misc/utmp/utent.c
index 336c0239b..a3f01b6e9 100644
--- a/libc/misc/utmp/utent.c
+++ b/libc/misc/utmp/utent.c
@@ -19,6 +19,7 @@
#include <errno.h>
#include <string.h>
#include <utmp.h>
+#include <not-cancel.h>
#include <bits/uClibc_mutex.h>
__UCLIBC_MUTEX_STATIC(utmplock, PTHREAD_MUTEX_INITIALIZER);
@@ -34,16 +35,16 @@ static const char *static_ut_name = default_file_name;
static void __setutent(void)
{
if (static_fd < 0) {
- static_fd = open(static_ut_name, O_RDWR | O_CLOEXEC);
+ static_fd = open_not_cancel_2(static_ut_name, O_RDWR | O_CLOEXEC);
if (static_fd < 0) {
- static_fd = open(static_ut_name, O_RDONLY | O_CLOEXEC);
+ static_fd = open_not_cancel_2(static_ut_name, O_RDONLY | O_CLOEXEC);
if (static_fd < 0) {
return; /* static_fd remains < 0 */
}
}
#ifndef __ASSUME_O_CLOEXEC
/* Make sure the file will be closed on exec() */
- fcntl(static_fd, F_SETFD, FD_CLOEXEC);
+ fcntl_not_cancel(static_fd, F_SETFD, FD_CLOEXEC);
#endif
return;
}
@@ -70,7 +71,7 @@ static struct utmp *__getutent(void)
}
}
- if (read(static_fd, &static_utmp, sizeof(static_utmp)) == sizeof(static_utmp)) {
+ if (read_not_cancel(static_fd, &static_utmp, sizeof(static_utmp)) == sizeof(static_utmp)) {
ret = &static_utmp;
}
@@ -81,7 +82,7 @@ void endutent(void)
{
__UCLIBC_MUTEX_LOCK(utmplock);
if (static_fd >= 0)
- close(static_fd);
+ close_not_cancel_no_status(static_fd);
static_fd = -1;
__UCLIBC_MUTEX_UNLOCK(utmplock);
}
@@ -182,7 +183,7 @@ int utmpname(const char *new_ut_name)
}
if (static_fd >= 0) {
- close(static_fd);
+ close_not_cancel_no_status(static_fd);
static_fd = -1;
}
__UCLIBC_MUTEX_UNLOCK(utmplock);
diff --git a/libc/misc/utmp/wtent.c b/libc/misc/utmp/wtent.c
index e73d99feb..5ab743d9b 100644
--- a/libc/misc/utmp/wtent.c
+++ b/libc/misc/utmp/wtent.c
@@ -13,6 +13,7 @@
#include <utmp.h>
#include <fcntl.h>
#include <sys/file.h>
+#include <not-cancel.h>
#if 0
/* This is enabled in uClibc/libutil/logwtmp.c */
@@ -36,12 +37,12 @@ void updwtmp(const char *wtmp_file, const struct utmp *lutmp)
{
int fd;
- fd = open(wtmp_file, O_APPEND | O_WRONLY);
+ fd = open_not_cancel(wtmp_file, O_APPEND | O_WRONLY, 0);
if (fd >= 0) {
if (lockf(fd, F_LOCK, 0) == 0) {
- write(fd, lutmp, sizeof(*lutmp));
+ write_not_cancel(fd, lutmp, sizeof(struct utmp));
lockf(fd, F_ULOCK, 0);
- close(fd);
+ close_not_cancel_no_status(fd);
}
}
}
diff --git a/libc/stdio/tmpfile.c b/libc/stdio/tmpfile.c
index 2f973c329..57f252715 100644
--- a/libc/stdio/tmpfile.c
+++ b/libc/stdio/tmpfile.c
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <unistd.h>
#include "../misc/internals/tempname.h"
+#include <not-cancel.h>
/* This returns a new stream opened on a temporary file (generated
@@ -43,7 +44,7 @@ FILE * tmpfile (void)
(void) remove (buf);
if ((f = fdopen (fd, "w+b")) == NULL)
- close (fd);
+ close_not_cancel (fd);
return f;
}
diff --git a/libc/sysdeps/linux/common/not-cancel.h b/libc/sysdeps/linux/common/not-cancel.h
new file mode 100644
index 000000000..ebdc6078d
--- /dev/null
+++ b/libc/sysdeps/linux/common/not-cancel.h
@@ -0,0 +1,19 @@
+/* By default we have none. Map the name to the normal functions. */
+#define open_not_cancel(name, flags, mode) \
+ open (name, flags, mode)
+#define open_not_cancel_2(name, flags) \
+ open (name, flags)
+#define close_not_cancel(fd) \
+ close (fd)
+#define close_not_cancel_no_status(fd) \
+ (void) close (fd)
+#define read_not_cancel(fd, buf, n) \
+ read (fd, buf, n)
+#define write_not_cancel(fd, buf, n) \
+ write (fd, buf, n)
+#define writev_not_cancel_no_status(fd, iov, n) \
+ (void) writev (fd, iov, n)
+#define fcntl_not_cancel(fd, cmd, val) \
+ fcntl (fd, cmd, val)
+# define waitpid_not_cancel(pid, stat_loc, options) \
+ waitpid (pid, stat_loc, options)
diff --git a/libc/unistd/daemon.c b/libc/unistd/daemon.c
index 741672ec0..c3b563179 100644
--- a/libc/unistd/daemon.c
+++ b/libc/unistd/daemon.c
@@ -46,6 +46,20 @@
#include <paths.h>
#include <signal.h>
#include <unistd.h>
+#include <not-cancel.h>
+#include <errno.h>
+
+#ifdef __UCLIBC_HAS_THREADS_NATIVE__
+#include <sys/stat.h>
+#endif
+
+#ifdef __UCLIBC_HAS_LFS__
+#define STAT stat64
+#define FSTAT fstat64
+#else
+#define STAT stat
+#define FSTAT fstat
+#endif
#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_UNIX98)
@@ -97,15 +111,40 @@ int daemon(int nochdir, int noclose)
if (setsid() == -1)
return -1;
+#ifndef __UCLIBC_HAS_THREADS_NATIVE__
+ /* Make certain we are not a session leader, or else we
+ * might reacquire a controlling terminal */
+ if (fork())
+ _exit(0);
+#endif
+
if (!nochdir)
chdir("/");
- if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR)) != -1) {
- dup2(fd, STDIN_FILENO);
- dup2(fd, STDOUT_FILENO);
- dup2(fd, STDERR_FILENO);
- if (fd > 2)
- close(fd);
+ if (!noclose)
+ {
+ struct STAT st;
+
+ if ((fd = open_not_cancel(_PATH_DEVNULL, O_RDWR, 0)) != -1
+ && (__builtin_expect (FSTAT (fd, &st), 0) == 0))
+ {
+ if (__builtin_expect (S_ISCHR (st.st_mode), 1) != 0) {
+ dup2(fd, STDIN_FILENO);
+ dup2(fd, STDOUT_FILENO);
+ dup2(fd, STDERR_FILENO);
+ if (fd > 2)
+ close(fd);
+ } else {
+ /* We must set an errno value since no
+ function call actually failed. */
+ close_not_cancel_no_status (fd);
+ __set_errno (ENODEV);
+ return -1;
+ }
+ } else {
+ close_not_cancel_no_status (fd);
+ return -1;
+ }
}
return 0;
}