libc_r: fix bugs in openat()
authorNicolas Thery <nthery@gmail.com>
Sun, 26 Jul 2009 18:40:46 +0000 (20:40 +0200)
committerNicolas Thery <nthery@gmail.com>
Sun, 26 Jul 2009 19:54:24 +0000 (21:54 +0200)
The openat() wrapper was not locking its file descriptor argument.

Special case the magic AT_FDCWD descriptor in the file descriptor
locking code (_FD_LOCK() / _FD_UNLOCK()) to avoid EINVAL on locking.

lib/libc_r/uthread/uthread_fd.c
lib/libc_r/uthread/uthread_open.c

index cf06446..7061ecb 100644 (file)
@@ -205,6 +205,12 @@ _thread_fd_unlock(int fd, int lock_type)
        int     ret;
 
        /*
+        * Early return if magic descriptor used by "at" family of syscalls.
+        */
+       if (fd == AT_FDCWD)
+               return (0);
+
+       /*
         * Check that the file descriptor table is initialised for this
         * entry: 
         */
@@ -325,6 +331,12 @@ _thread_fd_lock(int fd, int lock_type, struct timespec * timeout)
        int     ret;
 
        /*
+        * Early return if magic descriptor used by "at" family of syscalls.
+        */
+       if (fd == AT_FDCWD)
+               return (0);
+
+       /*
         * Check that the file descriptor table is initialised for this
         * entry: 
         */
@@ -519,6 +531,12 @@ _thread_fd_unlock_debug(int fd, int lock_type, char *fname, int lineno)
        int     ret;
 
        /*
+        * Early return if magic descriptor used by "at" family of syscalls.
+        */
+       if (fd == AT_FDCWD)
+               return (0);
+
+       /*
         * Check that the file descriptor table is initialised for this
         * entry: 
         */
@@ -640,6 +658,12 @@ _thread_fd_lock_debug(int fd, int lock_type, struct timespec * timeout,
        int     ret;
 
        /*
+        * Early return if magic descriptor used by "at" family of syscalls.
+        */
+       if (fd == AT_FDCWD)
+               return (0);
+
+       /*
         * Check that the file descriptor table is initialised for this
         * entry: 
         */
@@ -1022,9 +1046,9 @@ _thread_fd_lock(int fd, int lock_type, struct timespec * timeout)
 {
        /*
         * Insure that the file descriptor table is initialized for this
-        * entry
+        * entry except if magic descriptor used by "at" family of syscalls.
         */
-       return (_thread_fd_table_init(fd));
+       return ((fd != AT_FDCWD) ? _thread_fd_table_init(fd) : 0);
 }
 
 void
@@ -1038,9 +1062,9 @@ _thread_fd_lock_debug(int fd, int lock_type, struct timespec * timeout,
 {
        /*
         * Insure that the file descriptor table is initialized for this
-        * entry
+        * entry except if magic descriptor used by "at" family of syscalls.
         */
-       return (_thread_fd_table_init(fd));
+       return ((fd != AT_FDCWD) ? _thread_fd_table_init(fd) : 0);
 }
 
 void
index 24ce366..a095f28 100644 (file)
@@ -100,6 +100,10 @@ _openat(int fdbase, const char *path, int flags,...)
        int     fd;
        int     mode = 0;
        va_list ap;
+       int     error;
+
+       if ((error = _FD_LOCK(fdbase, FD_READ, NULL)) != 0)
+               return (error);
 
        /* Check if the file is being created: */
        if (flags & O_CREAT) {
@@ -120,6 +124,8 @@ _openat(int fdbase, const char *path, int flags,...)
                fd = -1;
        }
 
+       _FD_UNLOCK(fdbase, FD_READ);
+
        /* Return the file descriptor or -1 on error: */
        return (fd);
 }