Browse Source

use *_not_cancel variants to avoid accidental cancellations with nptl

Signed-off-by: Austin Foxley <austinf@cetoncorp.com>
Austin Foxley 14 years ago
parent
commit
9a737ab7a4

+ 8 - 7
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

+ 9 - 8
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

+ 2 - 1
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)

+ 6 - 4
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;

+ 7 - 6
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);

+ 4 - 3
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);
 	}
     }
 }

+ 2 - 1
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;
 }

+ 19 - 0
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)

+ 45 - 6
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;
 }