aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/compat.c14
-rw-r--r--fs/exec.c10
-rw-r--r--fs/internal.h2
-rw-r--r--fs/proc/base.c50
4 files changed, 32 insertions, 44 deletions
diff --git a/fs/compat.c b/fs/compat.c
index 5e374aad33f7..55efdfebdf5a 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1420,12 +1420,17 @@ int compat_do_execve(char * filename,
1420{ 1420{
1421 struct linux_binprm *bprm; 1421 struct linux_binprm *bprm;
1422 struct file *file; 1422 struct file *file;
1423 struct files_struct *displaced;
1423 int retval; 1424 int retval;
1424 1425
1426 retval = unshare_files(&displaced);
1427 if (retval)
1428 goto out_ret;
1429
1425 retval = -ENOMEM; 1430 retval = -ENOMEM;
1426 bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); 1431 bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
1427 if (!bprm) 1432 if (!bprm)
1428 goto out_ret; 1433 goto out_files;
1429 1434
1430 retval = mutex_lock_interruptible(&current->cred_exec_mutex); 1435 retval = mutex_lock_interruptible(&current->cred_exec_mutex);
1431 if (retval < 0) 1436 if (retval < 0)
@@ -1436,7 +1441,7 @@ int compat_do_execve(char * filename,
1436 bprm->cred = prepare_exec_creds(); 1441 bprm->cred = prepare_exec_creds();
1437 if (!bprm->cred) 1442 if (!bprm->cred)
1438 goto out_unlock; 1443 goto out_unlock;
1439 check_unsafe_exec(bprm, current->files); 1444 check_unsafe_exec(bprm);
1440 1445
1441 file = open_exec(filename); 1446 file = open_exec(filename);
1442 retval = PTR_ERR(file); 1447 retval = PTR_ERR(file);
@@ -1487,6 +1492,8 @@ int compat_do_execve(char * filename,
1487 mutex_unlock(&current->cred_exec_mutex); 1492 mutex_unlock(&current->cred_exec_mutex);
1488 acct_update_integrals(current); 1493 acct_update_integrals(current);
1489 free_bprm(bprm); 1494 free_bprm(bprm);
1495 if (displaced)
1496 put_files_struct(displaced);
1490 return retval; 1497 return retval;
1491 1498
1492out: 1499out:
@@ -1506,6 +1513,9 @@ out_unlock:
1506out_free: 1513out_free:
1507 free_bprm(bprm); 1514 free_bprm(bprm);
1508 1515
1516out_files:
1517 if (displaced)
1518 reset_files_struct(displaced);
1509out_ret: 1519out_ret:
1510 return retval; 1520 return retval;
1511} 1521}
diff --git a/fs/exec.c b/fs/exec.c
index b9f1c144b7a1..c5128fbc9165 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1056,28 +1056,24 @@ EXPORT_SYMBOL(install_exec_creds);
1056 * - the caller must hold current->cred_exec_mutex to protect against 1056 * - the caller must hold current->cred_exec_mutex to protect against
1057 * PTRACE_ATTACH 1057 * PTRACE_ATTACH
1058 */ 1058 */
1059void check_unsafe_exec(struct linux_binprm *bprm, struct files_struct *files) 1059void check_unsafe_exec(struct linux_binprm *bprm)
1060{ 1060{
1061 struct task_struct *p = current, *t; 1061 struct task_struct *p = current, *t;
1062 unsigned long flags; 1062 unsigned long flags;
1063 unsigned n_fs, n_files, n_sighand; 1063 unsigned n_fs, n_sighand;
1064 1064
1065 bprm->unsafe = tracehook_unsafe_exec(p); 1065 bprm->unsafe = tracehook_unsafe_exec(p);
1066 1066
1067 n_fs = 1; 1067 n_fs = 1;
1068 n_files = 1;
1069 n_sighand = 1; 1068 n_sighand = 1;
1070 lock_task_sighand(p, &flags); 1069 lock_task_sighand(p, &flags);
1071 for (t = next_thread(p); t != p; t = next_thread(t)) { 1070 for (t = next_thread(p); t != p; t = next_thread(t)) {
1072 if (t->fs == p->fs) 1071 if (t->fs == p->fs)
1073 n_fs++; 1072 n_fs++;
1074 if (t->files == files)
1075 n_files++;
1076 n_sighand++; 1073 n_sighand++;
1077 } 1074 }
1078 1075
1079 if (atomic_read(&p->fs->count) > n_fs || 1076 if (atomic_read(&p->fs->count) > n_fs ||
1080 atomic_read(&p->files->count) > n_files ||
1081 atomic_read(&p->sighand->count) > n_sighand) 1077 atomic_read(&p->sighand->count) > n_sighand)
1082 bprm->unsafe |= LSM_UNSAFE_SHARE; 1078 bprm->unsafe |= LSM_UNSAFE_SHARE;
1083 1079
@@ -1300,7 +1296,7 @@ int do_execve(char * filename,
1300 bprm->cred = prepare_exec_creds(); 1296 bprm->cred = prepare_exec_creds();
1301 if (!bprm->cred) 1297 if (!bprm->cred)
1302 goto out_unlock; 1298 goto out_unlock;
1303 check_unsafe_exec(bprm, displaced); 1299 check_unsafe_exec(bprm);
1304 1300
1305 file = open_exec(filename); 1301 file = open_exec(filename);
1306 retval = PTR_ERR(file); 1302 retval = PTR_ERR(file);
diff --git a/fs/internal.h b/fs/internal.h
index 0d8ac497b3d5..53af885f1732 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -43,7 +43,7 @@ extern void __init chrdev_init(void);
43/* 43/*
44 * exec.c 44 * exec.c
45 */ 45 */
46extern void check_unsafe_exec(struct linux_binprm *, struct files_struct *); 46extern void check_unsafe_exec(struct linux_binprm *);
47 47
48/* 48/*
49 * namespace.c 49 * namespace.c
diff --git a/fs/proc/base.c b/fs/proc/base.c
index aef6d55b7de6..e0afd326b688 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -146,15 +146,22 @@ static unsigned int pid_entry_count_dirs(const struct pid_entry *entries,
146 return count; 146 return count;
147} 147}
148 148
149static struct fs_struct *get_fs_struct(struct task_struct *task) 149static int get_fs_path(struct task_struct *task, struct path *path, bool root)
150{ 150{
151 struct fs_struct *fs; 151 struct fs_struct *fs;
152 int result = -ENOENT;
153
152 task_lock(task); 154 task_lock(task);
153 fs = task->fs; 155 fs = task->fs;
154 if(fs) 156 if (fs) {
155 atomic_inc(&fs->count); 157 read_lock(&fs->lock);
158 *path = root ? fs->root : fs->pwd;
159 path_get(path);
160 read_unlock(&fs->lock);
161 result = 0;
162 }
156 task_unlock(task); 163 task_unlock(task);
157 return fs; 164 return result;
158} 165}
159 166
160static int get_nr_threads(struct task_struct *tsk) 167static int get_nr_threads(struct task_struct *tsk)
@@ -172,42 +179,24 @@ static int get_nr_threads(struct task_struct *tsk)
172static int proc_cwd_link(struct inode *inode, struct path *path) 179static int proc_cwd_link(struct inode *inode, struct path *path)
173{ 180{
174 struct task_struct *task = get_proc_task(inode); 181 struct task_struct *task = get_proc_task(inode);
175 struct fs_struct *fs = NULL;
176 int result = -ENOENT; 182 int result = -ENOENT;
177 183
178 if (task) { 184 if (task) {
179 fs = get_fs_struct(task); 185 result = get_fs_path(task, path, 0);
180 put_task_struct(task); 186 put_task_struct(task);
181 } 187 }
182 if (fs) {
183 read_lock(&fs->lock);
184 *path = fs->pwd;
185 path_get(&fs->pwd);
186 read_unlock(&fs->lock);
187 result = 0;
188 put_fs_struct(fs);
189 }
190 return result; 188 return result;
191} 189}
192 190
193static int proc_root_link(struct inode *inode, struct path *path) 191static int proc_root_link(struct inode *inode, struct path *path)
194{ 192{
195 struct task_struct *task = get_proc_task(inode); 193 struct task_struct *task = get_proc_task(inode);
196 struct fs_struct *fs = NULL;
197 int result = -ENOENT; 194 int result = -ENOENT;
198 195
199 if (task) { 196 if (task) {
200 fs = get_fs_struct(task); 197 result = get_fs_path(task, path, 1);
201 put_task_struct(task); 198 put_task_struct(task);
202 } 199 }
203 if (fs) {
204 read_lock(&fs->lock);
205 *path = fs->root;
206 path_get(&fs->root);
207 read_unlock(&fs->lock);
208 result = 0;
209 put_fs_struct(fs);
210 }
211 return result; 200 return result;
212} 201}
213 202
@@ -596,7 +585,6 @@ static int mounts_open_common(struct inode *inode, struct file *file,
596 struct task_struct *task = get_proc_task(inode); 585 struct task_struct *task = get_proc_task(inode);
597 struct nsproxy *nsp; 586 struct nsproxy *nsp;
598 struct mnt_namespace *ns = NULL; 587 struct mnt_namespace *ns = NULL;
599 struct fs_struct *fs = NULL;
600 struct path root; 588 struct path root;
601 struct proc_mounts *p; 589 struct proc_mounts *p;
602 int ret = -EINVAL; 590 int ret = -EINVAL;
@@ -610,22 +598,16 @@ static int mounts_open_common(struct inode *inode, struct file *file,
610 get_mnt_ns(ns); 598 get_mnt_ns(ns);
611 } 599 }
612 rcu_read_unlock(); 600 rcu_read_unlock();
613 if (ns) 601 if (ns && get_fs_path(task, &root, 1) == 0)
614 fs = get_fs_struct(task); 602 ret = 0;
615 put_task_struct(task); 603 put_task_struct(task);
616 } 604 }
617 605
618 if (!ns) 606 if (!ns)
619 goto err; 607 goto err;
620 if (!fs) 608 if (ret)
621 goto err_put_ns; 609 goto err_put_ns;
622 610
623 read_lock(&fs->lock);
624 root = fs->root;
625 path_get(&root);
626 read_unlock(&fs->lock);
627 put_fs_struct(fs);
628
629 ret = -ENOMEM; 611 ret = -ENOMEM;
630 p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL); 612 p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);
631 if (!p) 613 if (!p)