Commit 1add9f7a authored by James Morris's avatar James Morris

[PATCH] sigio/sigurg cleanup for 2.5.32

This is a cleanup of the sigio/sigurg code.

Summary:
  o Removed sk->proc, SIGURG now sent via vfs, credentials checked
    during delivery.
  o SIOCSPGRP etc. ioctls use vfs, and work now for SIGIO as well
    as SIGURG.
  o Removed socket fcntl code.
  o Consolidate lsm file_set_fowner() hooks.
  o Fixed fowner race.
  o Fixed associated mainline memory leak in fcntl_dirnotify().
parent 22101408
...@@ -1458,15 +1458,9 @@ static int tty_fasync(int fd, struct file * filp, int on) ...@@ -1458,15 +1458,9 @@ static int tty_fasync(int fd, struct file * filp, int on)
if (on) { if (on) {
if (!waitqueue_active(&tty->read_wait)) if (!waitqueue_active(&tty->read_wait))
tty->minimum_to_wake = 1; tty->minimum_to_wake = 1;
if (filp->f_owner.pid == 0) { retval = f_setown(filp, (-tty->pgrp) ? : current->pid, 0);
retval = security_ops->file_set_fowner(filp); if (retval)
if (retval) return retval;
return retval;
filp->f_owner.pid = (-tty->pgrp) ? : current->pid;
filp->f_owner.uid = current->uid;
filp->f_owner.euid = current->euid;
}
} else { } else {
if (!tty->fasync && !waitqueue_active(&tty->read_wait)) if (!tty->fasync && !waitqueue_active(&tty->read_wait))
tty->minimum_to_wake = N_TTY_BUF_SIZE; tty->minimum_to_wake = N_TTY_BUF_SIZE;
......
...@@ -513,12 +513,10 @@ static int tun_chr_fasync(int fd, struct file *file, int on) ...@@ -513,12 +513,10 @@ static int tun_chr_fasync(int fd, struct file *file, int on)
return ret; return ret;
if (on) { if (on) {
ret = f_setown(file, current->pid, 0);
if (ret)
return ret;
tun->flags |= TUN_FASYNC; tun->flags |= TUN_FASYNC;
if (!file->f_owner.pid) {
file->f_owner.pid = current->pid;
file->f_owner.uid = current->uid;
file->f_owner.euid = current->euid;
}
} else } else
tun->flags &= ~TUN_FASYNC; tun->flags &= ~TUN_FASYNC;
......
...@@ -7,7 +7,8 @@ ...@@ -7,7 +7,8 @@
O_TARGET := fs.o O_TARGET := fs.o
export-objs := open.o dcache.o buffer.o bio.o inode.o dquot.o mpage.o aio.o export-objs := open.o dcache.o buffer.o bio.o inode.o dquot.o mpage.o aio.o \
fcntl.o
obj-y := open.o read_write.o devices.o file_table.o buffer.o \ obj-y := open.o read_write.o devices.o file_table.o buffer.o \
bio.o super.o block_dev.o char_dev.o stat.o exec.o pipe.o \ bio.o super.o block_dev.o char_dev.o stat.o exec.o pipe.o \
......
...@@ -68,7 +68,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg) ...@@ -68,7 +68,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
struct dnotify_struct **prev; struct dnotify_struct **prev;
struct inode *inode; struct inode *inode;
fl_owner_t id = current->files; fl_owner_t id = current->files;
int error; int error = 0;
if ((arg & ~DN_MULTISHOT) == 0) { if ((arg & ~DN_MULTISHOT) == 0) {
dnotify_flush(filp, id); dnotify_flush(filp, id);
...@@ -89,21 +89,15 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg) ...@@ -89,21 +89,15 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
odn->dn_fd = fd; odn->dn_fd = fd;
odn->dn_mask |= arg; odn->dn_mask |= arg;
inode->i_dnotify_mask |= arg & ~DN_MULTISHOT; inode->i_dnotify_mask |= arg & ~DN_MULTISHOT;
kmem_cache_free(dn_cache, dn); goto out_free;
goto out;
} }
prev = &odn->dn_next; prev = &odn->dn_next;
} }
error = security_ops->file_set_fowner(filp); error = f_setown(filp, current->pid, 1);
if (error) { if (error)
write_unlock(&dn_lock); goto out_free;
return error;
}
filp->f_owner.pid = current->pid;
filp->f_owner.uid = current->uid;
filp->f_owner.euid = current->euid;
dn->dn_mask = arg; dn->dn_mask = arg;
dn->dn_fd = fd; dn->dn_fd = fd;
dn->dn_filp = filp; dn->dn_filp = filp;
...@@ -113,7 +107,10 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg) ...@@ -113,7 +107,10 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
inode->i_dnotify = dn; inode->i_dnotify = dn;
out: out:
write_unlock(&dn_lock); write_unlock(&dn_lock);
return 0; return error;
out_free:
kmem_cache_free(dn_cache, dn);
goto out;
} }
void __inode_dir_notify(struct inode *inode, unsigned long event) void __inode_dir_notify(struct inode *inode, unsigned long event)
...@@ -131,8 +128,7 @@ void __inode_dir_notify(struct inode *inode, unsigned long event) ...@@ -131,8 +128,7 @@ void __inode_dir_notify(struct inode *inode, unsigned long event)
continue; continue;
} }
fown = &dn->dn_filp->f_owner; fown = &dn->dn_filp->f_owner;
if (fown->pid) send_sigio(fown, dn->dn_fd, POLL_MSG);
send_sigio(fown, dn->dn_fd, POLL_MSG);
if (dn->dn_mask & DN_MULTISHOT) if (dn->dn_mask & DN_MULTISHOT)
prev = &dn->dn_next; prev = &dn->dn_next;
else { else {
......
...@@ -11,13 +11,13 @@ ...@@ -11,13 +11,13 @@
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/iobuf.h> #include <linux/iobuf.h>
#include <linux/module.h>
#include <linux/security.h> #include <linux/security.h>
#include <asm/poll.h> #include <asm/poll.h>
#include <asm/siginfo.h> #include <asm/siginfo.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
extern int sock_fcntl (struct file *, unsigned int cmd, unsigned long arg);
extern int fcntl_setlease(unsigned int fd, struct file *filp, long arg); extern int fcntl_setlease(unsigned int fd, struct file *filp, long arg);
extern int fcntl_getlease(struct file *filp); extern int fcntl_getlease(struct file *filp);
...@@ -260,6 +260,35 @@ static int setfl(int fd, struct file * filp, unsigned long arg) ...@@ -260,6 +260,35 @@ static int setfl(int fd, struct file * filp, unsigned long arg)
return 0; return 0;
} }
static void f_modown(struct file *filp, unsigned long pid,
uid_t uid, uid_t euid, int force)
{
write_lock_irq(&filp->f_owner.lock);
if (force || !filp->f_owner.pid) {
filp->f_owner.pid = pid;
filp->f_owner.uid = uid;
filp->f_owner.euid = euid;
}
write_unlock_irq(&filp->f_owner.lock);
}
int f_setown(struct file *filp, unsigned long arg, int force)
{
int err;
err = security_ops->file_set_fowner(filp);
if (err)
return err;
f_modown(filp, arg, current->uid, current->euid, force);
return 0;
}
void f_delown(struct file *filp)
{
f_modown(filp, 0, 0, 0, 1);
}
static long do_fcntl(unsigned int fd, unsigned int cmd, static long do_fcntl(unsigned int fd, unsigned int cmd,
unsigned long arg, struct file * filp) unsigned long arg, struct file * filp)
{ {
...@@ -305,21 +334,7 @@ static long do_fcntl(unsigned int fd, unsigned int cmd, ...@@ -305,21 +334,7 @@ static long do_fcntl(unsigned int fd, unsigned int cmd,
err = filp->f_owner.pid; err = filp->f_owner.pid;
break; break;
case F_SETOWN: case F_SETOWN:
lock_kernel(); err = f_setown(filp, arg, 1);
err = security_ops->file_set_fowner(filp);
if (err) {
unlock_kernel();
break;
}
filp->f_owner.pid = arg;
filp->f_owner.uid = current->uid;
filp->f_owner.euid = current->euid;
err = 0;
if (S_ISSOCK (filp->f_dentry->d_inode->i_mode))
err = sock_fcntl (filp, F_SETOWN, arg);
unlock_kernel();
break; break;
case F_GETSIG: case F_GETSIG:
err = filp->f_owner.signum; err = filp->f_owner.signum;
...@@ -342,10 +357,6 @@ static long do_fcntl(unsigned int fd, unsigned int cmd, ...@@ -342,10 +357,6 @@ static long do_fcntl(unsigned int fd, unsigned int cmd,
err = fcntl_dirnotify(fd, filp, arg); err = fcntl_dirnotify(fd, filp, arg);
break; break;
default: default:
/* sockets need a few special fcntls. */
err = -EINVAL;
if (S_ISSOCK (filp->f_dentry->d_inode->i_mode))
err = sock_fcntl (filp, cmd, arg);
break; break;
} }
...@@ -421,14 +432,20 @@ static long band_table[NSIGPOLL] = { ...@@ -421,14 +432,20 @@ static long band_table[NSIGPOLL] = {
POLLHUP | POLLERR /* POLL_HUP */ POLLHUP | POLLERR /* POLL_HUP */
}; };
static inline int sigio_perm(struct task_struct *p,
struct fown_struct *fown)
{
return ((fown->euid == 0) ||
(fown->euid == p->suid) || (fown->euid == p->uid) ||
(fown->uid == p->suid) || (fown->uid == p->uid));
}
static void send_sigio_to_task(struct task_struct *p, static void send_sigio_to_task(struct task_struct *p,
struct fown_struct *fown, struct fown_struct *fown,
int fd, int fd,
int reason) int reason)
{ {
if ((fown->euid != 0) && if (!sigio_perm(p, fown))
(fown->euid ^ p->suid) && (fown->euid ^ p->uid) &&
(fown->uid ^ p->suid) && (fown->uid ^ p->uid))
return; return;
if (security_ops->file_send_sigiotask(p, fown, fd, reason)) if (security_ops->file_send_sigiotask(p, fown, fd, reason))
...@@ -467,12 +484,17 @@ static void send_sigio_to_task(struct task_struct *p, ...@@ -467,12 +484,17 @@ static void send_sigio_to_task(struct task_struct *p,
void send_sigio(struct fown_struct *fown, int fd, int band) void send_sigio(struct fown_struct *fown, int fd, int band)
{ {
struct task_struct * p; struct task_struct * p;
int pid = fown->pid; int pid;
read_lock(&fown->lock);
pid = fown->pid;
if (!pid)
goto out_unlock_fown;
read_lock(&tasklist_lock); read_lock(&tasklist_lock);
if ( (pid > 0) && (p = find_task_by_pid(pid)) ) { if ( (pid > 0) && (p = find_task_by_pid(pid)) ) {
send_sigio_to_task(p, fown, fd, band); send_sigio_to_task(p, fown, fd, band);
goto out; goto out_unlock_task;
} }
for_each_task(p) { for_each_task(p) {
int match = p->pid; int match = p->pid;
...@@ -482,8 +504,49 @@ void send_sigio(struct fown_struct *fown, int fd, int band) ...@@ -482,8 +504,49 @@ void send_sigio(struct fown_struct *fown, int fd, int band)
continue; continue;
send_sigio_to_task(p, fown, fd, band); send_sigio_to_task(p, fown, fd, band);
} }
out: out_unlock_task:
read_unlock(&tasklist_lock);
out_unlock_fown:
read_unlock(&fown->lock);
}
static void send_sigurg_to_task(struct task_struct *p,
struct fown_struct *fown)
{
if (sigio_perm(p, fown))
send_sig(SIGURG, p, 1);
}
int send_sigurg(struct fown_struct *fown)
{
struct task_struct *p;
int pid, ret = 0;
read_lock(&fown->lock);
pid = fown->pid;
if (!pid)
goto out_unlock_fown;
ret = 1;
read_lock(&tasklist_lock);
if ((pid > 0) && (p = find_task_by_pid(pid))) {
send_sigurg_to_task(p, fown);
goto out_unlock_task;
}
for_each_task(p) {
int match = p->pid;
if (pid < 0)
match = -p->pgrp;
if (pid != match)
continue;
send_sigurg_to_task(p, fown);
}
out_unlock_task:
read_unlock(&tasklist_lock); read_unlock(&tasklist_lock);
out_unlock_fown:
read_unlock(&fown->lock);
return ret;
} }
static rwlock_t fasync_lock = RW_LOCK_UNLOCKED; static rwlock_t fasync_lock = RW_LOCK_UNLOCKED;
...@@ -546,7 +609,7 @@ void __kill_fasync(struct fasync_struct *fa, int sig, int band) ...@@ -546,7 +609,7 @@ void __kill_fasync(struct fasync_struct *fa, int sig, int band)
/* Don't send SIGURG to processes which have not set a /* Don't send SIGURG to processes which have not set a
queued signum: SIGURG has its own default signalling queued signum: SIGURG has its own default signalling
mechanism. */ mechanism. */
if (fown->pid && !(sig == SIGURG && fown->signum == 0)) if (!(sig == SIGURG && fown->signum == 0))
send_sigio(fown, fa->fa_fd, band); send_sigio(fown, fa->fa_fd, band);
fa = fa->fa_next; fa = fa->fa_next;
} }
...@@ -569,3 +632,6 @@ static int __init fasync_init(void) ...@@ -569,3 +632,6 @@ static int __init fasync_init(void)
} }
module_init(fasync_init) module_init(fasync_init)
EXPORT_SYMBOL(f_setown);
EXPORT_SYMBOL(f_delown);
...@@ -54,6 +54,7 @@ struct file * get_empty_filp(void) ...@@ -54,6 +54,7 @@ struct file * get_empty_filp(void)
f->f_version = ++event; f->f_version = ++event;
f->f_uid = current->fsuid; f->f_uid = current->fsuid;
f->f_gid = current->fsgid; f->f_gid = current->fsgid;
f->f_owner.lock = RW_LOCK_UNLOCKED;
list_add(&f->f_list, &anon_list); list_add(&f->f_list, &anon_list);
file_list_unlock(); file_list_unlock();
return f; return f;
......
...@@ -997,9 +997,7 @@ static int lease_modify(struct file_lock **before, int arg) ...@@ -997,9 +997,7 @@ static int lease_modify(struct file_lock **before, int arg)
if (arg == F_UNLCK) { if (arg == F_UNLCK) {
struct file *filp = fl->fl_file; struct file *filp = fl->fl_file;
filp->f_owner.pid = 0; f_delown(filp);
filp->f_owner.uid = 0;
filp->f_owner.euid = 0;
filp->f_owner.signum = 0; filp->f_owner.signum = 0;
locks_delete_lock(before); locks_delete_lock(before);
} }
...@@ -1277,13 +1275,7 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg) ...@@ -1277,13 +1275,7 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
*before = fl; *before = fl;
list_add(&fl->fl_link, &file_lock_list); list_add(&fl->fl_link, &file_lock_list);
error = security_ops->file_set_fowner(filp); error = f_setown(filp, current->pid, 1);
if (error)
goto out_unlock;
filp->f_owner.pid = current->pid;
filp->f_owner.uid = current->uid;
filp->f_owner.euid = current->euid;
out_unlock: out_unlock:
unlock_kernel(); unlock_kernel();
return error; return error;
......
...@@ -432,6 +432,7 @@ static inline struct inode *SOCK_INODE(struct socket *socket) ...@@ -432,6 +432,7 @@ static inline struct inode *SOCK_INODE(struct socket *socket)
#include <linux/efs_fs_i.h> #include <linux/efs_fs_i.h>
struct fown_struct { struct fown_struct {
rwlock_t lock; /* protects pid, uid, euid fields */
int pid; /* pid or -pgrp where SIGIO should be sent */ int pid; /* pid or -pgrp where SIGIO should be sent */
uid_t uid, euid; /* uid/euid of process setting the owner */ uid_t uid, euid; /* uid/euid of process setting the owner */
int signum; /* posix.1b rt signal to be delivered on IO */ int signum; /* posix.1b rt signal to be delivered on IO */
...@@ -615,6 +616,10 @@ extern void kill_fasync(struct fasync_struct **, int, int); ...@@ -615,6 +616,10 @@ extern void kill_fasync(struct fasync_struct **, int, int);
/* only for net: no internal synchronization */ /* only for net: no internal synchronization */
extern void __kill_fasync(struct fasync_struct *, int, int); extern void __kill_fasync(struct fasync_struct *, int, int);
extern int f_setown(struct file *filp, unsigned long arg, int force);
extern void f_delown(struct file *filp);
extern int send_sigurg(struct fown_struct *fown);
/* /*
* Umount options * Umount options
*/ */
......
...@@ -34,9 +34,6 @@ extern int inet_setsockopt(struct socket *sock, int level, ...@@ -34,9 +34,6 @@ extern int inet_setsockopt(struct socket *sock, int level,
extern int inet_getsockopt(struct socket *sock, int level, extern int inet_getsockopt(struct socket *sock, int level,
int optname, char *optval, int optname, char *optval,
int *optlen); int *optlen);
extern int inet_fcntl(struct socket *sock,
unsigned int cmd,
unsigned long arg);
extern int inet_listen(struct socket *sock, int backlog); extern int inet_listen(struct socket *sock, int backlog);
extern void inet_sock_release(struct sock *sk); extern void inet_sock_release(struct sock *sk);
......
...@@ -132,7 +132,6 @@ struct sock { ...@@ -132,7 +132,6 @@ struct sock {
unsigned char rcvtstamp; unsigned char rcvtstamp;
/* Hole of 1 byte. Try to pack. */ /* Hole of 1 byte. Try to pack. */
int route_caps; int route_caps;
int proc;
unsigned long lingertime; unsigned long lingertime;
int hashent; int hashent;
...@@ -292,7 +291,6 @@ static __inline__ void sock_prot_dec_use(struct proto *prot) ...@@ -292,7 +291,6 @@ static __inline__ void sock_prot_dec_use(struct proto *prot)
#define SOCK_BINDADDR_LOCK 4 #define SOCK_BINDADDR_LOCK 4
#define SOCK_BINDPORT_LOCK 8 #define SOCK_BINDPORT_LOCK 8
#include <linux/fs.h> /* just for inode - yeuch.*/
/* Used by processes to "lock" a socket state, so that /* Used by processes to "lock" a socket state, so that
...@@ -362,6 +360,7 @@ extern struct sk_buff *sock_alloc_send_pskb(struct sock *sk, ...@@ -362,6 +360,7 @@ extern struct sk_buff *sock_alloc_send_pskb(struct sock *sk,
int *errcode); int *errcode);
extern void *sock_kmalloc(struct sock *sk, int size, int priority); extern void *sock_kmalloc(struct sock *sk, int size, int priority);
extern void sock_kfree_s(struct sock *sk, void *mem, int size); extern void sock_kfree_s(struct sock *sk, void *mem, int size);
extern void sk_send_sigurg(struct sock *sk);
/* /*
* Functions to fill in entries in struct proto_ops when a protocol * Functions to fill in entries in struct proto_ops when a protocol
...@@ -388,8 +387,6 @@ extern int sock_no_getsockopt(struct socket *, int , int, ...@@ -388,8 +387,6 @@ extern int sock_no_getsockopt(struct socket *, int , int,
char *, int *); char *, int *);
extern int sock_no_setsockopt(struct socket *, int, int, extern int sock_no_setsockopt(struct socket *, int, int,
char *, int); char *, int);
extern int sock_no_fcntl(struct socket *,
unsigned int, unsigned long);
extern int sock_no_sendmsg(struct socket *, extern int sock_no_sendmsg(struct socket *,
struct msghdr *, int, struct msghdr *, int,
struct scm_cookie *); struct scm_cookie *);
......
...@@ -276,9 +276,14 @@ static int futex_fd(struct list_head *head, ...@@ -276,9 +276,14 @@ static int futex_fd(struct list_head *head,
filp->f_dentry = dget(futex_mnt->mnt_root); filp->f_dentry = dget(futex_mnt->mnt_root);
if (signal) { if (signal) {
filp->f_owner.pid = current->tgid; int ret;
filp->f_owner.uid = current->uid;
filp->f_owner.euid = current->euid; ret = f_setown(filp, current->tgid, 1);
if (ret) {
put_unused_fd(fd);
put_filp(filp);
return ret;
}
filp->f_owner.signum = signal; filp->f_owner.signum = signal;
} }
......
...@@ -103,7 +103,6 @@ ...@@ -103,7 +103,6 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/sockios.h> #include <linux/sockios.h>
#include <linux/net.h> #include <linux/net.h>
#include <linux/fcntl.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -1048,34 +1047,6 @@ int sock_no_getsockopt(struct socket *sock, int level, int optname, ...@@ -1048,34 +1047,6 @@ int sock_no_getsockopt(struct socket *sock, int level, int optname,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
/*
* Note: if you add something that sleeps here then change sock_fcntl()
* to do proper fd locking.
*/
int sock_no_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
struct sock *sk = sock->sk;
switch(cmd)
{
case F_SETOWN:
/*
* This is a little restrictive, but it's the only
* way to make sure that you can't send a sigurg to
* another process.
*/
if (current->pgrp != -arg &&
current->pid != arg &&
!capable(CAP_KILL)) return(-EPERM);
sk->proc = arg;
return(0);
case F_GETOWN:
return(sk->proc);
default:
return(-EINVAL);
}
}
int sock_no_sendmsg(struct socket *sock, struct msghdr *m, int flags, int sock_no_sendmsg(struct socket *sock, struct msghdr *m, int flags,
struct scm_cookie *scm) struct scm_cookie *scm)
{ {
...@@ -1179,6 +1150,13 @@ void sock_def_destruct(struct sock *sk) ...@@ -1179,6 +1150,13 @@ void sock_def_destruct(struct sock *sk)
kfree(sk->protinfo); kfree(sk->protinfo);
} }
void sk_send_sigurg(struct sock *sk)
{
if (sk->socket && sk->socket->file)
if (send_sigurg(&sk->socket->file->f_owner))
sk_wake_async(sk, 3, POLL_PRI);
}
void sock_init_data(struct socket *sock, struct sock *sk) void sock_init_data(struct socket *sock, struct sock *sk)
{ {
skb_queue_head_init(&sk->receive_queue); skb_queue_head_init(&sk->receive_queue);
......
...@@ -651,13 +651,10 @@ static int econet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg ...@@ -651,13 +651,10 @@ static int econet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg
case SIOCSPGRP: case SIOCSPGRP:
if (get_user(pid, (int *) arg)) if (get_user(pid, (int *) arg))
return -EFAULT; return -EFAULT;
if (current->pid != pid && current->pgrp != -pid && !capable(CAP_NET_ADMIN)) return f_setown(sock->file, pid, 1);
return -EPERM;
sk->proc = pid;
return(0);
case FIOGETOWN: case FIOGETOWN:
case SIOCGPGRP: case SIOCGPGRP:
return put_user(sk->proc, (int *)arg); return put_user(sock->file->f_owner.pid, (int *)arg);
case SIOCGSTAMP: case SIOCGSTAMP:
if(sk->stamp.tv_sec==0) if(sk->stamp.tv_sec==0)
return -ENOENT; return -ENOENT;
......
...@@ -857,16 +857,12 @@ static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -857,16 +857,12 @@ static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCSPGRP: case SIOCSPGRP:
if (get_user(pid, (int *)arg)) if (get_user(pid, (int *)arg))
err = -EFAULT; err = -EFAULT;
else if (current->pid != pid &&
current->pgrp != -pid &&
!capable(CAP_NET_ADMIN))
err = -EPERM;
else else
sk->proc = pid; err = f_setown(sock->file, pid, 1);
break; break;
case FIOGETOWN: case FIOGETOWN:
case SIOCGPGRP: case SIOCGPGRP:
err = put_user(sk->proc, (int *)arg); err = put_user(sock->file->f_owner.pid, (int *)arg);
break; break;
case SIOCGSTAMP: case SIOCGSTAMP:
if (!sk->stamp.tv_sec) if (!sk->stamp.tv_sec)
......
...@@ -3093,13 +3093,7 @@ static void tcp_check_urg(struct sock * sk, struct tcphdr * th) ...@@ -3093,13 +3093,7 @@ static void tcp_check_urg(struct sock * sk, struct tcphdr * th)
return; return;
/* Tell the world about our new urgent pointer. */ /* Tell the world about our new urgent pointer. */
if (sk->proc != 0) { sk_send_sigurg(sk);
if (sk->proc > 0)
kill_proc(sk->proc, SIGURG, 1);
else
kill_pg(-sk->proc, SIGURG, 1);
sk_wake_async(sk, 3, POLL_PRI);
}
/* We may be adding urgent data when the last byte read was /* We may be adding urgent data when the last byte read was
* urgent. To do this requires some care. We cannot just ignore * urgent. To do this requires some care. We cannot just ignore
......
...@@ -676,7 +676,6 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req, ...@@ -676,7 +676,6 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
newsk->done = 0; newsk->done = 0;
newsk->userlocks = sk->userlocks & ~SOCK_BINDPORT_LOCK; newsk->userlocks = sk->userlocks & ~SOCK_BINDPORT_LOCK;
newsk->proc = 0;
newsk->backlog.head = newsk->backlog.tail = NULL; newsk->backlog.head = newsk->backlog.tail = NULL;
newsk->callback_lock = RW_LOCK_UNLOCKED; newsk->callback_lock = RW_LOCK_UNLOCKED;
skb_queue_head_init(&newsk->error_queue); skb_queue_head_init(&newsk->error_queue);
......
...@@ -463,15 +463,10 @@ static int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -463,15 +463,10 @@ static int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCSPGRP: case SIOCSPGRP:
if (get_user(pid, (int *) arg)) if (get_user(pid, (int *) arg))
return -EFAULT; return -EFAULT;
/* see sock_no_fcntl */ return f_setown(sock->file, pid, 1);
if (current->pid != pid && current->pgrp != -pid &&
!capable(CAP_NET_ADMIN))
return -EPERM;
sk->proc = pid;
return(0);
case FIOGETOWN: case FIOGETOWN:
case SIOCGPGRP: case SIOCGPGRP:
return put_user(sk->proc,(int *)arg); return put_user(sock->file->f_owner.pid, (int *)arg);
case SIOCGSTAMP: case SIOCGSTAMP:
if(sk->stamp.tv_sec==0) if(sk->stamp.tv_sec==0)
return -ENOENT; return -ENOENT;
......
...@@ -1463,15 +1463,11 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd, ...@@ -1463,15 +1463,11 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd,
int pid; int pid;
if (get_user(pid, (int *) arg)) if (get_user(pid, (int *) arg))
return -EFAULT; return -EFAULT;
if (current->pid != pid && current->pgrp != -pid && return f_setown(sock->file, pid, 1);
!capable(CAP_NET_ADMIN))
return -EPERM;
sk->proc = pid;
break;
} }
case FIOGETOWN: case FIOGETOWN:
case SIOCGPGRP: case SIOCGPGRP:
return put_user(sk->proc, (int *)arg); return put_user(sock->file->f_owner.pid, (int *)arg);
case SIOCGSTAMP: case SIOCGSTAMP:
if(sk->stamp.tv_sec==0) if(sk->stamp.tv_sec==0)
return -ENOENT; return -ENOENT;
......
...@@ -1516,24 +1516,6 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr *msg, unsigned int flags) ...@@ -1516,24 +1516,6 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr *msg, unsigned int flags)
return err; return err;
} }
/*
* Perform a file control on a socket file descriptor.
*
* Doesn't acquire a fd lock, because no network fcntl
* function sleeps currently.
*/
int sock_fcntl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct socket *sock;
sock = SOCKET_I (filp->f_dentry->d_inode);
if (sock && sock->ops)
return sock_no_fcntl(sock, cmd, arg);
return(-EINVAL);
}
/* Argument list sizes for sys_socketcall */ /* Argument list sizes for sys_socketcall */
#define AL(x) ((x) * sizeof(unsigned long)) #define AL(x) ((x) * sizeof(unsigned long))
static unsigned char nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), static unsigned char nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
......
...@@ -1876,14 +1876,10 @@ static int wanpipe_ioctl(struct socket *sock, unsigned int cmd, unsigned long ar ...@@ -1876,14 +1876,10 @@ static int wanpipe_ioctl(struct socket *sock, unsigned int cmd, unsigned long ar
err = get_user(pid, (int *) arg); err = get_user(pid, (int *) arg);
if (err) if (err)
return err; return err;
if (current->pid != pid && current->pgrp != -pid && return f_setown(sock->file, pid, 1);
!capable(CAP_NET_ADMIN))
return -EPERM;
sk->proc = pid;
return(0);
case FIOGETOWN: case FIOGETOWN:
case SIOCGPGRP: case SIOCGPGRP:
return put_user(sk->proc, (int *)arg); return put_user(sock->file->f_owner.pid, (int *)arg);
case SIOCGSTAMP: case SIOCGSTAMP:
if(sk->stamp.tv_sec==0) if(sk->stamp.tv_sec==0)
return -ENOENT; return -ENOENT;
......
...@@ -283,13 +283,7 @@ static int x25_state3_machine(struct sock *sk, struct sk_buff *skb, int frametyp ...@@ -283,13 +283,7 @@ static int x25_state3_machine(struct sock *sk, struct sk_buff *skb, int frametyp
skb_queue_tail(&x25->interrupt_in_queue, skb); skb_queue_tail(&x25->interrupt_in_queue, skb);
queued = 1; queued = 1;
} }
if (sk->proc != 0) { sk_send_sigurg(sk);
if (sk->proc > 0)
kill_proc(sk->proc, SIGURG, 1);
else
kill_pg(-sk->proc, SIGURG, 1);
sock_wake_async(sk->socket, 3, POLL_PRI);
}
x25_write_internal(sk, X25_INTERRUPT_CONFIRMATION); x25_write_internal(sk, X25_INTERRUPT_CONFIRMATION);
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment