git://git.onelab.eu
/
linux-2.6.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git]
/
fs
/
fcntl.c
diff --git
a/fs/fcntl.c
b/fs/fcntl.c
index
59d2706
..
921b556
100644
(file)
--- a/
fs/fcntl.c
+++ b/
fs/fcntl.c
@@
-9,6
+9,7
@@
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/file.h>
+#include <linux/capability.h>
#include <linux/dnotify.h>
#include <linux/smp_lock.h>
#include <linux/slab.h>
#include <linux/dnotify.h>
#include <linux/smp_lock.h>
#include <linux/slab.h>
@@
-16,6
+17,7
@@
#include <linux/security.h>
#include <linux/ptrace.h>
#include <linux/signal.h>
#include <linux/security.h>
#include <linux/ptrace.h>
#include <linux/signal.h>
+#include <linux/rcupdate.h>
#include <linux/vs_limit.h>
#include <asm/poll.h>
#include <linux/vs_limit.h>
#include <asm/poll.h>
@@
-25,21
+27,25
@@
void fastcall set_close_on_exec(unsigned int fd, int flag)
{
struct files_struct *files = current->files;
void fastcall set_close_on_exec(unsigned int fd, int flag)
{
struct files_struct *files = current->files;
+ struct fdtable *fdt;
spin_lock(&files->file_lock);
spin_lock(&files->file_lock);
+ fdt = files_fdtable(files);
if (flag)
if (flag)
- FD_SET(fd, f
iles
->close_on_exec);
+ FD_SET(fd, f
dt
->close_on_exec);
else
else
- FD_CLR(fd, f
iles
->close_on_exec);
+ FD_CLR(fd, f
dt
->close_on_exec);
spin_unlock(&files->file_lock);
}
spin_unlock(&files->file_lock);
}
-static in
line in
t get_close_on_exec(unsigned int fd)
+static int get_close_on_exec(unsigned int fd)
{
struct files_struct *files = current->files;
{
struct files_struct *files = current->files;
+ struct fdtable *fdt;
int res;
int res;
- spin_lock(&files->file_lock);
- res = FD_ISSET(fd, files->close_on_exec);
- spin_unlock(&files->file_lock);
+ rcu_read_lock();
+ fdt = files_fdtable(files);
+ res = FD_ISSET(fd, fdt->close_on_exec);
+ rcu_read_unlock();
return res;
}
return res;
}
@@
-55,24
+61,26
@@
static int locate_fd(struct files_struct *files,
unsigned int newfd;
unsigned int start;
int error;
unsigned int newfd;
unsigned int start;
int error;
+ struct fdtable *fdt;
error = -EINVAL;
if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
goto out;
repeat:
error = -EINVAL;
if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
goto out;
repeat:
+ fdt = files_fdtable(files);
/*
* Someone might have closed fd's in the range
/*
* Someone might have closed fd's in the range
- * orig_start..f
iles
->next_fd
+ * orig_start..f
dt
->next_fd
*/
start = orig_start;
if (start < files->next_fd)
start = files->next_fd;
newfd = start;
*/
start = orig_start;
if (start < files->next_fd)
start = files->next_fd;
newfd = start;
- if (start < f
iles
->max_fdset) {
- newfd = find_next_zero_bit(f
iles
->open_fds->fds_bits,
- f
iles
->max_fdset, start);
+ if (start < f
dt
->max_fdset) {
+ newfd = find_next_zero_bit(f
dt
->open_fds->fds_bits,
+ f
dt
->max_fdset, start);
}
error = -EMFILE;
}
error = -EMFILE;
@@
-92,25
+100,33
@@
repeat:
if (error)
goto repeat;
if (error)
goto repeat;
+ /*
+ * We reacquired files_lock, so we are safe as long as
+ * we reacquire the fdtable pointer and use it while holding
+ * the lock, no one can free it during that time.
+ */
if (start <= files->next_fd)
files->next_fd = newfd + 1;
if (start <= files->next_fd)
files->next_fd = newfd + 1;
-
+
error = newfd;
out:
return error;
}
error = newfd;
out:
return error;
}
-
static
int dupfd(struct file *file, unsigned int start)
+int dupfd(struct file *file, unsigned int start)
{
struct files_struct * files = current->files;
{
struct files_struct * files = current->files;
+ struct fdtable *fdt;
int fd;
spin_lock(&files->file_lock);
fd = locate_fd(files, file, start);
if (fd >= 0) {
int fd;
spin_lock(&files->file_lock);
fd = locate_fd(files, file, start);
if (fd >= 0) {
- FD_SET(fd, files->open_fds);
- FD_CLR(fd, files->close_on_exec);
+ /* locate_fd() may have expanded fdtable, load the ptr */
+ fdt = files_fdtable(files);
+ FD_SET(fd, fdt->open_fds);
+ FD_CLR(fd, fdt->close_on_exec);
spin_unlock(&files->file_lock);
vx_openfd_inc(fd);
fd_install(fd, file);
spin_unlock(&files->file_lock);
vx_openfd_inc(fd);
fd_install(fd, file);
@@
-122,11
+138,14
@@
static int dupfd(struct file *file, unsigned int start)
return fd;
}
return fd;
}
+EXPORT_SYMBOL_GPL(dupfd);
+
asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
{
int err = -EBADF;
struct file * file, *tofree;
struct files_struct * files = current->files;
asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
{
int err = -EBADF;
struct file * file, *tofree;
struct files_struct * files = current->files;
+ struct fdtable *fdt;
spin_lock(&files->file_lock);
if (!(file = fcheck(oldfd)))
spin_lock(&files->file_lock);
if (!(file = fcheck(oldfd)))
@@
-152,13
+171,14
@@
asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
/* Yes. It's a race. In user space. Nothing sane to do */
err = -EBUSY;
/* Yes. It's a race. In user space. Nothing sane to do */
err = -EBUSY;
- tofree = files->fd[newfd];
- if (!tofree && FD_ISSET(newfd, files->open_fds))
+ fdt = files_fdtable(files);
+ tofree = fdt->fd[newfd];
+ if (!tofree && FD_ISSET(newfd, fdt->open_fds))
goto out_fput;
goto out_fput;
-
files->fd[newfd] = file
;
- FD_SET(newfd, f
iles
->open_fds);
- FD_CLR(newfd, f
iles
->close_on_exec);
+
rcu_assign_pointer(fdt->fd[newfd], file)
;
+ FD_SET(newfd, f
dt
->open_fds);
+ FD_CLR(newfd, f
dt
->close_on_exec);
spin_unlock(&files->file_lock);
if (tofree)
spin_unlock(&files->file_lock);
if (tofree)
@@
-196,8
+216,11
@@
static int setfl(int fd, struct file * filp, unsigned long arg)
struct inode * inode = filp->f_dentry->d_inode;
int error = 0;
struct inode * inode = filp->f_dentry->d_inode;
int error = 0;
- /* O_APPEND cannot be cleared if the file is marked as append-only */
- if (!(arg & O_APPEND) && IS_APPEND(inode))
+ /*
+ * O_APPEND cannot be cleared if the file is marked as append-only
+ * and the file is open for write.
+ */
+ if (((arg ^ filp->f_flags) & O_APPEND) && IS_APPEND(inode))
return -EPERM;
/* O_NOATIME can only be set by the owner or superuser */
return -EPERM;
/* O_NOATIME can only be set by the owner or superuser */
@@
-295,7
+318,7
@@
static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
break;
case F_SETLK:
case F_SETLKW:
break;
case F_SETLK:
case F_SETLKW:
- err = fcntl_setlk(filp, cmd, (struct flock __user *) arg);
+ err = fcntl_setlk(f
d, f
ilp, cmd, (struct flock __user *) arg);
break;
case F_GETOWN:
/*
break;
case F_GETOWN:
/*
@@
-383,7
+406,8
@@
asmlinkage long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg
break;
case F_SETLK64:
case F_SETLKW64:
break;
case F_SETLK64:
case F_SETLKW64:
- err = fcntl_setlk64(filp, cmd, (struct flock64 __user *) arg);
+ err = fcntl_setlk64(fd, filp, cmd,
+ (struct flock64 __user *) arg);
break;
default:
err = do_fcntl(fd, cmd, arg, filp);
break;
default:
err = do_fcntl(fd, cmd, arg, filp);
@@
-397,7
+421,7
@@
out:
/* Table to convert sigio signal codes into poll band bitmaps */
/* Table to convert sigio signal codes into poll band bitmaps */
-static long band_table[NSIGPOLL] = {
+static
const
long band_table[NSIGPOLL] = {
POLLIN | POLLRDNORM, /* POLL_IN */
POLLOUT | POLLWRNORM | POLLWRBAND, /* POLL_OUT */
POLLIN | POLLRDNORM | POLLMSG, /* POLL_MSG */
POLLIN | POLLRDNORM, /* POLL_IN */
POLLOUT | POLLWRNORM | POLLWRBAND, /* POLL_OUT */
POLLIN | POLLRDNORM | POLLMSG, /* POLL_MSG */
@@
-438,18
+462,17
@@
static void send_sigio_to_task(struct task_struct *p,
/* Make sure we are called with one of the POLL_*
reasons, otherwise we could leak kernel stack into
userspace. */
/* Make sure we are called with one of the POLL_*
reasons, otherwise we could leak kernel stack into
userspace. */
- if ((reason & __SI_MASK) != __SI_POLL)
- BUG();
+ BUG_ON((reason & __SI_MASK) != __SI_POLL);
if (reason - POLL_IN >= NSIGPOLL)
si.si_band = ~0L;
else
si.si_band = band_table[reason - POLL_IN];
si.si_fd = fd;
if (reason - POLL_IN >= NSIGPOLL)
si.si_band = ~0L;
else
si.si_band = band_table[reason - POLL_IN];
si.si_fd = fd;
- if (!
send_group
_sig_info(fown->signum, &si, p))
+ if (!
group_send
_sig_info(fown->signum, &si, p))
break;
/* fall-through: fall back on the old plain SIGIO signal */
case 0:
break;
/* fall-through: fall back on the old plain SIGIO signal */
case 0:
-
send_group
_sig_info(SIGIO, SEND_SIG_PRIV, p);
+
group_send
_sig_info(SIGIO, SEND_SIG_PRIV, p);
}
}
}
}
@@
-483,7
+506,7
@@
static void send_sigurg_to_task(struct task_struct *p,
struct fown_struct *fown)
{
if (sigio_perm(p, fown, SIGURG))
struct fown_struct *fown)
{
if (sigio_perm(p, fown, SIGURG))
-
send_group
_sig_info(SIGURG, SEND_SIG_PRIV, p);
+
group_send
_sig_info(SIGURG, SEND_SIG_PRIV, p);
}
int send_sigurg(struct fown_struct *fown)
}
int send_sigurg(struct fown_struct *fown)
@@
-516,7
+539,7
@@
int send_sigurg(struct fown_struct *fown)
}
static DEFINE_RWLOCK(fasync_lock);
}
static DEFINE_RWLOCK(fasync_lock);
-static kmem_cache_t *fasync_cache;
+static kmem_cache_t *fasync_cache
__read_mostly
;
/*
* fasync_helper() is used by some character device drivers (mainly mice)
/*
* fasync_helper() is used by some character device drivers (mainly mice)