summaryrefslogtreecommitdiffstats
path: root/fs/fcntl.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2017-06-14 09:11:54 -0400
committerJeff Layton <jlayton@redhat.com>2017-06-14 09:11:54 -0400
commitf73127356f344483c82632accda2e72b7e0e5f25 (patch)
treea28efd5ab23bd502147d4267590ea1c79dc74b64 /fs/fcntl.c
parentfc3dc67471461c0efcb1ed22fb7595121d65fad9 (diff)
fs/fcntl: return -ESRCH in f_setown when pid/pgid can't be found
The current implementation of F_SETOWN doesn't properly vet the argument passed in and only returns an error if INT_MIN is passed in. If the argument doesn't specify a valid pid/pgid, then we just end up cleaning out the file->f_owner structure. What we really want is to only clean that out only in the case where userland passed in an argument of 0. For anything else, we want to return ESRCH if it doesn't refer to a valid pid. The relevant POSIX spec page is here: http://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html Cc: Jiri Slaby <jslaby@suse.cz> Cc: zhong jiang <zhongjiang@huawei.com> Signed-off-by: Jeff Layton <jlayton@redhat.com>
Diffstat (limited to 'fs/fcntl.c')
-rw-r--r--fs/fcntl.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 693322e28751..afed3b364979 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -112,8 +112,9 @@ EXPORT_SYMBOL(__f_setown);
112int f_setown(struct file *filp, unsigned long arg, int force) 112int f_setown(struct file *filp, unsigned long arg, int force)
113{ 113{
114 enum pid_type type; 114 enum pid_type type;
115 struct pid *pid; 115 struct pid *pid = NULL;
116 int who = arg; 116 int who = arg, ret = 0;
117
117 type = PIDTYPE_PID; 118 type = PIDTYPE_PID;
118 if (who < 0) { 119 if (who < 0) {
119 /* avoid overflow below */ 120 /* avoid overflow below */
@@ -123,12 +124,19 @@ int f_setown(struct file *filp, unsigned long arg, int force)
123 type = PIDTYPE_PGID; 124 type = PIDTYPE_PGID;
124 who = -who; 125 who = -who;
125 } 126 }
127
126 rcu_read_lock(); 128 rcu_read_lock();
127 pid = find_vpid(who); 129 if (who) {
128 __f_setown(filp, pid, type, force); 130 pid = find_vpid(who);
131 if (!pid)
132 ret = -ESRCH;
133 }
134
135 if (!ret)
136 __f_setown(filp, pid, type, force);
129 rcu_read_unlock(); 137 rcu_read_unlock();
130 138
131 return 0; 139 return ret;
132} 140}
133EXPORT_SYMBOL(f_setown); 141EXPORT_SYMBOL(f_setown);
134 142