X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Ffcntl.c;h=c9ae39bda81287beb5eeaf220d47868a73491891;hb=804f448fadfb16effa3f62acf9f171b0c774c306;hp=68b3d561c16aec18b88e274751707a8db63fbd35;hpb=bc77d24c47b89f1e0efed0b8e4be5f8aad102883;p=linux-2.6.git diff --git a/fs/fcntl.c b/fs/fcntl.c index 68b3d561c..c9ae39bda 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -4,6 +4,7 @@ * Copyright (C) 1991, 1992 Linus Torvalds */ +#include #include #include #include @@ -14,6 +15,8 @@ #include #include #include +#include +#include #include #include @@ -40,38 +43,6 @@ static inline int get_close_on_exec(unsigned int fd) return res; } - -/* Expand files. Return <0 on error; 0 nothing done; 1 files expanded, - * we may have blocked. - * - * Should be called with the files->file_lock spinlock held for write. - */ -static int expand_files(struct files_struct *files, int nr) -{ - int err, expand = 0; -#ifdef FDSET_DEBUG - printk (KERN_ERR "%s %d: nr = %d\n", __FUNCTION__, current->pid, nr); -#endif - - if (nr >= files->max_fdset) { - expand = 1; - if ((err = expand_fdset(files, nr))) - goto out; - } - if (nr >= files->max_fds) { - expand = 1; - if ((err = expand_fd_array(files, nr))) - goto out; - } - err = expand; - out: -#ifdef FDSET_DEBUG - if (err) - printk (KERN_ERR "%s %d: return %d\n", __FUNCTION__, current->pid, err); -#endif - return err; -} - /* * locate_fd finds a free file descriptor in the open_fds fdset, * expanding the fd arrays if necessary. Must be called with the @@ -86,7 +57,7 @@ static int locate_fd(struct files_struct *files, int error; error = -EINVAL; - if (orig_start >= current->rlim[RLIMIT_NOFILE].rlim_cur) + if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) goto out; repeat: @@ -105,7 +76,9 @@ repeat: } error = -EMFILE; - if (newfd >= current->rlim[RLIMIT_NOFILE].rlim_cur) + if (newfd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) + goto out; + if (!vx_files_avail(1)) goto out; error = expand_files(files, newfd); @@ -139,6 +112,7 @@ int dupfd(struct file *file, unsigned int start) FD_SET(fd, files->open_fds); FD_CLR(fd, files->close_on_exec); spin_unlock(&files->file_lock); + vx_openfd_inc(fd); fd_install(fd, file); } else { spin_unlock(&files->file_lock); @@ -163,7 +137,7 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd) if (newfd == oldfd) goto out_unlock; err = -EBADF; - if (newfd >= current->rlim[RLIMIT_NOFILE].rlim_cur) + if (newfd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) goto out_unlock; get_file(file); /* We are now finished with oldfd */ @@ -188,9 +162,13 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd) FD_SET(newfd, files->open_fds); FD_CLR(newfd, files->close_on_exec); spin_unlock(&files->file_lock); + // vx_openfd_inc(newfd); if (tofree) filp_close(tofree, files); + else + vx_openfd_inc(newfd); /* fd was unused */ + err = newfd; out: return err; @@ -214,7 +192,7 @@ asmlinkage long sys_dup(unsigned int fildes) return ret; } -#define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC | O_DIRECT) +#define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC | O_DIRECT | O_NOATIME) static int setfl(int fd, struct file * filp, unsigned long arg) { @@ -225,6 +203,11 @@ static int setfl(int fd, struct file * filp, unsigned long arg) if (!(arg & O_APPEND) && IS_APPEND(inode)) return -EPERM; + /* O_NOATIME can only be set by the owner or superuser */ + if ((arg & O_NOATIME) && !(filp->f_flags & O_NOATIME)) + if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER)) + return -EPERM; + /* required for strict SunOS emulation */ if (O_NONBLOCK != O_NDELAY) if (arg & O_NDELAY) @@ -236,6 +219,11 @@ static int setfl(int fd, struct file * filp, unsigned long arg) return -EINVAL; } + if (filp->f_op && filp->f_op->check_flags) + error = filp->f_op->check_flags(arg); + if (error) + return error; + lock_kernel(); if ((arg ^ filp->f_flags) & FASYNC) { if (filp->f_op && filp->f_op->fasync) { @@ -282,10 +270,8 @@ void f_delown(struct file *filp) f_modown(filp, 0, 0, 0, 1); } -EXPORT_SYMBOL(f_delown); - -long generic_file_fcntl(int fd, unsigned int cmd, - unsigned long arg, struct file *filp) +static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, + struct file *filp) { long err = -EINVAL; @@ -333,7 +319,7 @@ long generic_file_fcntl(int fd, unsigned int cmd, break; case F_SETSIG: /* arg == 0 restores default behaviour. */ - if (arg < 0 || arg > _NSIG) { + if (!valid_signal(arg)) { break; } err = 0; @@ -353,17 +339,8 @@ long generic_file_fcntl(int fd, unsigned int cmd, } return err; } -EXPORT_SYMBOL(generic_file_fcntl); -static long do_fcntl(int fd, unsigned int cmd, - unsigned long arg, struct file *filp) -{ - if (filp->f_op && filp->f_op->fcntl) - return filp->f_op->fcntl(fd, cmd, arg, filp); - return generic_file_fcntl(fd, cmd, arg, filp); -} - -asmlinkage long sys_fcntl(int fd, unsigned int cmd, unsigned long arg) +asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) { struct file *filp; long err = -EBADF; @@ -433,11 +410,12 @@ static long band_table[NSIGPOLL] = { }; static inline int sigio_perm(struct task_struct *p, - struct fown_struct *fown) + struct fown_struct *fown, int sig) { - return ((fown->euid == 0) || - (fown->euid == p->suid) || (fown->euid == p->uid) || - (fown->uid == p->suid) || (fown->uid == p->uid)); + return (((fown->euid == 0) || + (fown->euid == p->suid) || (fown->euid == p->uid) || + (fown->uid == p->suid) || (fown->uid == p->uid)) && + !security_file_send_sigiotask(p, fown, sig)); } static void send_sigio_to_task(struct task_struct *p, @@ -445,10 +423,7 @@ static void send_sigio_to_task(struct task_struct *p, int fd, int reason) { - if (!sigio_perm(p, fown)) - return; - - if (security_file_send_sigiotask(p, fown, fd, reason)) + if (!sigio_perm(p, fown, fown->signum)) return; switch (fown->signum) { @@ -473,7 +448,7 @@ static void send_sigio_to_task(struct task_struct *p, else si.si_band = band_table[reason - POLL_IN]; si.si_fd = fd; - if (!send_sig_info(fown->signum, &si, p)) + if (!send_group_sig_info(fown->signum, &si, p)) break; /* fall-through: fall back on the old plain SIGIO signal */ case 0: @@ -493,16 +468,14 @@ void send_sigio(struct fown_struct *fown, int fd, int band) read_lock(&tasklist_lock); if (pid > 0) { - p = find_task_by_pid(pid); + p = find_task_by_real_pid(pid); if (p) { send_sigio_to_task(p, fown, fd, band); } } else { - struct list_head *l; - struct pid *pidptr; - for_each_task_pid(-pid, PIDTYPE_PGID, p, l, pidptr) { + do_each_task_pid(-pid, PIDTYPE_PGID, p) { send_sigio_to_task(p, fown, fd, band); - } + } while_each_task_pid(-pid, PIDTYPE_PGID, p); } read_unlock(&tasklist_lock); out_unlock_fown: @@ -512,7 +485,7 @@ void send_sigio(struct fown_struct *fown, int fd, int band) static void send_sigurg_to_task(struct task_struct *p, struct fown_struct *fown) { - if (sigio_perm(p, fown)) + if (sigio_perm(p, fown, SIGURG)) send_group_sig_info(SIGURG, SEND_SIG_PRIV, p); } @@ -530,16 +503,14 @@ int send_sigurg(struct fown_struct *fown) read_lock(&tasklist_lock); if (pid > 0) { - p = find_task_by_pid(pid); + p = find_task_by_real_pid(pid); if (p) { send_sigurg_to_task(p, fown); } } else { - struct list_head *l; - struct pid *pidptr; - for_each_task_pid(-pid, PIDTYPE_PGID, p, l, pidptr) { + do_each_task_pid(-pid, PIDTYPE_PGID, p) { send_sigurg_to_task(p, fown); - } + } while_each_task_pid(-pid, PIDTYPE_PGID, p); } read_unlock(&tasklist_lock); out_unlock_fown: @@ -547,7 +518,7 @@ int send_sigurg(struct fown_struct *fown) return ret; } -static rwlock_t fasync_lock = RW_LOCK_UNLOCKED; +static DEFINE_RWLOCK(fasync_lock); static kmem_cache_t *fasync_cache; /*