* Copyright (C) 1991, 1992 Linus Torvalds
*/
+#include <linux/syscalls.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/security.h>
#include <linux/ptrace.h>
+#include <linux/vs_limit.h>
#include <asm/poll.h>
#include <asm/siginfo.h>
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
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:
}
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);
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);
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 */
if (tofree)
filp_close(tofree, files);
+ else
+ vx_openfd_inc(newfd); /* fd was unused */
+
err = newfd;
out:
return err;
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)
{
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)
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) {
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;
}
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;
};
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,
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) {
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:
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);
}
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:
return ret;
}
-static rwlock_t fasync_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(fasync_lock);
static kmem_cache_t *fasync_cache;
/*
read_unlock(&fasync_lock);
}
}
-
EXPORT_SYMBOL(kill_fasync);
static int __init fasync_init(void)
{
fasync_cache = kmem_cache_create("fasync_cache",
- sizeof(struct fasync_struct), 0, 0, NULL, NULL);
- if (!fasync_cache)
- panic("cannot create fasync slab cache");
+ sizeof(struct fasync_struct), 0, SLAB_PANIC, NULL, NULL);
return 0;
}