fs/Kconfig: move btrfs out
[safe/jmp/linux-2.6] / fs / compat.c
index 133ed7f..65a070e 100644 (file)
@@ -137,6 +137,45 @@ asmlinkage long compat_sys_utimes(char __user *filename, struct compat_timeval _
        return compat_sys_futimesat(AT_FDCWD, filename, t);
 }
 
+static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf)
+{
+       compat_ino_t ino = stat->ino;
+       typeof(ubuf->st_uid) uid = 0;
+       typeof(ubuf->st_gid) gid = 0;
+       int err;
+
+       SET_UID(uid, stat->uid);
+       SET_GID(gid, stat->gid);
+
+       if ((u64) stat->size > MAX_NON_LFS ||
+           !old_valid_dev(stat->dev) ||
+           !old_valid_dev(stat->rdev))
+               return -EOVERFLOW;
+       if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino)
+               return -EOVERFLOW;
+
+       if (clear_user(ubuf, sizeof(*ubuf)))
+               return -EFAULT;
+
+       err  = __put_user(old_encode_dev(stat->dev), &ubuf->st_dev);
+       err |= __put_user(ino, &ubuf->st_ino);
+       err |= __put_user(stat->mode, &ubuf->st_mode);
+       err |= __put_user(stat->nlink, &ubuf->st_nlink);
+       err |= __put_user(uid, &ubuf->st_uid);
+       err |= __put_user(gid, &ubuf->st_gid);
+       err |= __put_user(old_encode_dev(stat->rdev), &ubuf->st_rdev);
+       err |= __put_user(stat->size, &ubuf->st_size);
+       err |= __put_user(stat->atime.tv_sec, &ubuf->st_atime);
+       err |= __put_user(stat->atime.tv_nsec, &ubuf->st_atime_nsec);
+       err |= __put_user(stat->mtime.tv_sec, &ubuf->st_mtime);
+       err |= __put_user(stat->mtime.tv_nsec, &ubuf->st_mtime_nsec);
+       err |= __put_user(stat->ctime.tv_sec, &ubuf->st_ctime);
+       err |= __put_user(stat->ctime.tv_nsec, &ubuf->st_ctime_nsec);
+       err |= __put_user(stat->blksize, &ubuf->st_blksize);
+       err |= __put_user(stat->blocks, &ubuf->st_blocks);
+       return err;
+}
+
 asmlinkage long compat_sys_newstat(char __user * filename,
                struct compat_stat __user *statbuf)
 {
@@ -830,7 +869,7 @@ asmlinkage long compat_sys_old_readdir(unsigned int fd,
        buf.dirent = dirent;
 
        error = vfs_readdir(file, compat_fillonedir, &buf);
-       if (error >= 0)
+       if (buf.result)
                error = buf.result;
 
        fput(file);
@@ -917,9 +956,8 @@ asmlinkage long compat_sys_getdents(unsigned int fd,
        buf.error = 0;
 
        error = vfs_readdir(file, compat_filldir, &buf);
-       if (error < 0)
-               goto out_putf;
-       error = buf.error;
+       if (error >= 0)
+               error = buf.error;
        lastdirent = buf.previous;
        if (lastdirent) {
                if (put_user(file->f_pos, &lastdirent->d_off))
@@ -927,8 +965,6 @@ asmlinkage long compat_sys_getdents(unsigned int fd,
                else
                        error = count - buf.count;
        }
-
-out_putf:
        fput(file);
 out:
        return error;
@@ -1008,19 +1044,16 @@ asmlinkage long compat_sys_getdents64(unsigned int fd,
        buf.error = 0;
 
        error = vfs_readdir(file, compat_filldir64, &buf);
-       if (error < 0)
-               goto out_putf;
-       error = buf.error;
+       if (error >= 0)
+               error = buf.error;
        lastdirent = buf.previous;
        if (lastdirent) {
                typeof(lastdirent->d_off) d_off = file->f_pos;
-               error = -EFAULT;
                if (__put_user_unaligned(d_off, &lastdirent->d_off))
-                       goto out_putf;
-               error = count - buf.count;
+                       error = -EFAULT;
+               else
+                       error = count - buf.count;
        }
-
-out_putf:
        fput(file);
 out:
        return error;
@@ -1154,6 +1187,9 @@ compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, unsign
        ret = compat_do_readv_writev(READ, file, vec, vlen, &file->f_pos);
 
 out:
+       if (ret > 0)
+               add_rchar(current, ret);
+       inc_syscr(current);
        fput(file);
        return ret;
 }
@@ -1177,6 +1213,9 @@ compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, unsig
        ret = compat_do_readv_writev(WRITE, file, vec, vlen, &file->f_pos);
 
 out:
+       if (ret > 0)
+               add_wchar(current, ret);
+       inc_syscw(current);
        fput(file);
        return ret;
 }
@@ -1239,7 +1278,7 @@ static int compat_count(compat_uptr_t __user *argv, int max)
                        if (!p)
                                break;
                        argv++;
-                       if(++i > max)
+                       if (i++ >= max)
                                return -E2BIG;
                }
        }
@@ -1360,10 +1399,20 @@ int compat_do_execve(char * filename,
        if (!bprm)
                goto out_ret;
 
+       retval = mutex_lock_interruptible(&current->cred_exec_mutex);
+       if (retval < 0)
+               goto out_free;
+
+       retval = -ENOMEM;
+       bprm->cred = prepare_exec_creds();
+       if (!bprm->cred)
+               goto out_unlock;
+       check_unsafe_exec(bprm);
+
        file = open_exec(filename);
        retval = PTR_ERR(file);
        if (IS_ERR(file))
-               goto out_kfree;
+               goto out_unlock;
 
        sched_exec();
 
@@ -1377,14 +1426,10 @@ int compat_do_execve(char * filename,
 
        bprm->argc = compat_count(argv, MAX_ARG_STRINGS);
        if ((retval = bprm->argc) < 0)
-               goto out_mm;
+               goto out;
 
        bprm->envc = compat_count(envp, MAX_ARG_STRINGS);
        if ((retval = bprm->envc) < 0)
-               goto out_mm;
-
-       retval = security_bprm_alloc(bprm);
-       if (retval)
                goto out;
 
        retval = prepare_binprm(bprm);
@@ -1405,19 +1450,16 @@ int compat_do_execve(char * filename,
                goto out;
 
        retval = search_binary_handler(bprm, regs);
-       if (retval >= 0) {
-               /* execve success */
-               security_bprm_free(bprm);
-               acct_update_integrals(current);
-               free_bprm(bprm);
-               return retval;
-       }
+       if (retval < 0)
+               goto out;
 
-out:
-       if (bprm->security)
-               security_bprm_free(bprm);
+       /* execve succeeded */
+       mutex_unlock(&current->cred_exec_mutex);
+       acct_update_integrals(current);
+       free_bprm(bprm);
+       return retval;
 
-out_mm:
+out:
        if (bprm->mm)
                mmput(bprm->mm);
 
@@ -1427,7 +1469,10 @@ out_file:
                fput(bprm->file);
        }
 
-out_kfree:
+out_unlock:
+       mutex_unlock(&current->cred_exec_mutex);
+
+out_free:
        free_bprm(bprm);
 
 out_ret:
@@ -1651,8 +1696,9 @@ asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
                        return -EFAULT;
 
                to = &end_time;
-               if (poll_select_set_timeout(to, tv.tv_sec,
-                                           tv.tv_usec * NSEC_PER_USEC))
+               if (poll_select_set_timeout(to,
+                               tv.tv_sec + (tv.tv_usec / USEC_PER_SEC),
+                               (tv.tv_usec % USEC_PER_SEC) * NSEC_PER_USEC))
                        return -EINVAL;
        }
 
@@ -1663,7 +1709,7 @@ asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
 }
 
 #ifdef HAVE_SET_RESTORE_SIGMASK
-asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
+static long do_compat_pselect(int n, compat_ulong_t __user *inp,
        compat_ulong_t __user *outp, compat_ulong_t __user *exp,
        struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask,
        compat_size_t sigsetsize)
@@ -1729,8 +1775,8 @@ asmlinkage long compat_sys_pselect6(int n, compat_ulong_t __user *inp,
                                (compat_size_t __user *)(sig+sizeof(up))))
                        return -EFAULT;
        }
-       return compat_sys_pselect7(n, inp, outp, exp, tsp, compat_ptr(up),
-                                       sigsetsize);
+       return do_compat_pselect(n, inp, outp, exp, tsp, compat_ptr(up),
+                                sigsetsize);
 }
 
 asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,