diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/exec.c | 31 | ||||
-rw-r--r-- | fs/nfsd/auth.c | 92 | ||||
-rw-r--r-- | fs/nfsd/nfs4recover.c | 68 | ||||
-rw-r--r-- | fs/nfsd/nfsfh.c | 11 | ||||
-rw-r--r-- | fs/open.c | 31 |
5 files changed, 138 insertions, 95 deletions
@@ -1007,13 +1007,12 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
1007 | */ | 1007 | */ |
1008 | current->mm->task_size = TASK_SIZE; | 1008 | current->mm->task_size = TASK_SIZE; |
1009 | 1009 | ||
1010 | if (bprm->e_uid != current_euid() || bprm->e_gid != current_egid()) { | 1010 | if (bprm->e_uid != current_euid() || |
1011 | suid_keys(current); | 1011 | bprm->e_gid != current_egid()) { |
1012 | set_dumpable(current->mm, suid_dumpable); | 1012 | set_dumpable(current->mm, suid_dumpable); |
1013 | current->pdeath_signal = 0; | 1013 | current->pdeath_signal = 0; |
1014 | } else if (file_permission(bprm->file, MAY_READ) || | 1014 | } else if (file_permission(bprm->file, MAY_READ) || |
1015 | (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) { | 1015 | (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) { |
1016 | suid_keys(current); | ||
1017 | set_dumpable(current->mm, suid_dumpable); | 1016 | set_dumpable(current->mm, suid_dumpable); |
1018 | } | 1017 | } |
1019 | 1018 | ||
@@ -1096,10 +1095,8 @@ void compute_creds(struct linux_binprm *bprm) | |||
1096 | { | 1095 | { |
1097 | int unsafe; | 1096 | int unsafe; |
1098 | 1097 | ||
1099 | if (bprm->e_uid != current_uid()) { | 1098 | if (bprm->e_uid != current_uid()) |
1100 | suid_keys(current); | ||
1101 | current->pdeath_signal = 0; | 1099 | current->pdeath_signal = 0; |
1102 | } | ||
1103 | exec_keys(current); | 1100 | exec_keys(current); |
1104 | 1101 | ||
1105 | task_lock(current); | 1102 | task_lock(current); |
@@ -1709,8 +1706,9 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
1709 | struct linux_binfmt * binfmt; | 1706 | struct linux_binfmt * binfmt; |
1710 | struct inode * inode; | 1707 | struct inode * inode; |
1711 | struct file * file; | 1708 | struct file * file; |
1709 | const struct cred *old_cred; | ||
1710 | struct cred *cred; | ||
1712 | int retval = 0; | 1711 | int retval = 0; |
1713 | int fsuid = current_fsuid(); | ||
1714 | int flag = 0; | 1712 | int flag = 0; |
1715 | int ispipe = 0; | 1713 | int ispipe = 0; |
1716 | unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; | 1714 | unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; |
@@ -1723,12 +1721,20 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
1723 | binfmt = current->binfmt; | 1721 | binfmt = current->binfmt; |
1724 | if (!binfmt || !binfmt->core_dump) | 1722 | if (!binfmt || !binfmt->core_dump) |
1725 | goto fail; | 1723 | goto fail; |
1724 | |||
1725 | cred = prepare_creds(); | ||
1726 | if (!cred) { | ||
1727 | retval = -ENOMEM; | ||
1728 | goto fail; | ||
1729 | } | ||
1730 | |||
1726 | down_write(&mm->mmap_sem); | 1731 | down_write(&mm->mmap_sem); |
1727 | /* | 1732 | /* |
1728 | * If another thread got here first, or we are not dumpable, bail out. | 1733 | * If another thread got here first, or we are not dumpable, bail out. |
1729 | */ | 1734 | */ |
1730 | if (mm->core_state || !get_dumpable(mm)) { | 1735 | if (mm->core_state || !get_dumpable(mm)) { |
1731 | up_write(&mm->mmap_sem); | 1736 | up_write(&mm->mmap_sem); |
1737 | put_cred(cred); | ||
1732 | goto fail; | 1738 | goto fail; |
1733 | } | 1739 | } |
1734 | 1740 | ||
@@ -1739,12 +1745,16 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
1739 | */ | 1745 | */ |
1740 | if (get_dumpable(mm) == 2) { /* Setuid core dump mode */ | 1746 | if (get_dumpable(mm) == 2) { /* Setuid core dump mode */ |
1741 | flag = O_EXCL; /* Stop rewrite attacks */ | 1747 | flag = O_EXCL; /* Stop rewrite attacks */ |
1742 | current->cred->fsuid = 0; /* Dump root private */ | 1748 | cred->fsuid = 0; /* Dump root private */ |
1743 | } | 1749 | } |
1744 | 1750 | ||
1745 | retval = coredump_wait(exit_code, &core_state); | 1751 | retval = coredump_wait(exit_code, &core_state); |
1746 | if (retval < 0) | 1752 | if (retval < 0) { |
1753 | put_cred(cred); | ||
1747 | goto fail; | 1754 | goto fail; |
1755 | } | ||
1756 | |||
1757 | old_cred = override_creds(cred); | ||
1748 | 1758 | ||
1749 | /* | 1759 | /* |
1750 | * Clear any false indication of pending signals that might | 1760 | * Clear any false indication of pending signals that might |
@@ -1835,7 +1845,8 @@ fail_unlock: | |||
1835 | if (helper_argv) | 1845 | if (helper_argv) |
1836 | argv_free(helper_argv); | 1846 | argv_free(helper_argv); |
1837 | 1847 | ||
1838 | current->cred->fsuid = fsuid; | 1848 | revert_creds(old_cred); |
1849 | put_cred(cred); | ||
1839 | coredump_finish(mm); | 1850 | coredump_finish(mm); |
1840 | fail: | 1851 | fail: |
1841 | return retval; | 1852 | return retval; |
diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c index 808fc03a6fbd..836ffa1047d9 100644 --- a/fs/nfsd/auth.c +++ b/fs/nfsd/auth.c | |||
@@ -27,55 +27,67 @@ int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp) | |||
27 | 27 | ||
28 | int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp) | 28 | int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp) |
29 | { | 29 | { |
30 | struct cred *act_as = current->cred ; | 30 | struct group_info *rqgi; |
31 | struct svc_cred cred = rqstp->rq_cred; | 31 | struct group_info *gi; |
32 | struct cred *new; | ||
32 | int i; | 33 | int i; |
33 | int flags = nfsexp_flags(rqstp, exp); | 34 | int flags = nfsexp_flags(rqstp, exp); |
34 | int ret; | 35 | int ret; |
35 | 36 | ||
37 | new = prepare_creds(); | ||
38 | if (!new) | ||
39 | return -ENOMEM; | ||
40 | |||
41 | new->fsuid = rqstp->rq_cred.cr_uid; | ||
42 | new->fsgid = rqstp->rq_cred.cr_gid; | ||
43 | |||
44 | rqgi = rqstp->rq_cred.cr_group_info; | ||
45 | |||
36 | if (flags & NFSEXP_ALLSQUASH) { | 46 | if (flags & NFSEXP_ALLSQUASH) { |
37 | cred.cr_uid = exp->ex_anon_uid; | 47 | new->fsuid = exp->ex_anon_uid; |
38 | cred.cr_gid = exp->ex_anon_gid; | 48 | new->fsgid = exp->ex_anon_gid; |
39 | cred.cr_group_info = groups_alloc(0); | 49 | gi = groups_alloc(0); |
40 | } else if (flags & NFSEXP_ROOTSQUASH) { | 50 | } else if (flags & NFSEXP_ROOTSQUASH) { |
41 | struct group_info *gi; | 51 | if (!new->fsuid) |
42 | if (!cred.cr_uid) | 52 | new->fsuid = exp->ex_anon_uid; |
43 | cred.cr_uid = exp->ex_anon_uid; | 53 | if (!new->fsgid) |
44 | if (!cred.cr_gid) | 54 | new->fsgid = exp->ex_anon_gid; |
45 | cred.cr_gid = exp->ex_anon_gid; | ||
46 | gi = groups_alloc(cred.cr_group_info->ngroups); | ||
47 | if (gi) | ||
48 | for (i = 0; i < cred.cr_group_info->ngroups; i++) { | ||
49 | if (!GROUP_AT(cred.cr_group_info, i)) | ||
50 | GROUP_AT(gi, i) = exp->ex_anon_gid; | ||
51 | else | ||
52 | GROUP_AT(gi, i) = GROUP_AT(cred.cr_group_info, i); | ||
53 | } | ||
54 | cred.cr_group_info = gi; | ||
55 | } else | ||
56 | get_group_info(cred.cr_group_info); | ||
57 | |||
58 | if (cred.cr_uid != (uid_t) -1) | ||
59 | act_as->fsuid = cred.cr_uid; | ||
60 | else | ||
61 | act_as->fsuid = exp->ex_anon_uid; | ||
62 | if (cred.cr_gid != (gid_t) -1) | ||
63 | act_as->fsgid = cred.cr_gid; | ||
64 | else | ||
65 | act_as->fsgid = exp->ex_anon_gid; | ||
66 | 55 | ||
67 | if (!cred.cr_group_info) | 56 | gi = groups_alloc(rqgi->ngroups); |
68 | return -ENOMEM; | 57 | if (!gi) |
69 | ret = set_groups(act_as, cred.cr_group_info); | 58 | goto oom; |
70 | put_group_info(cred.cr_group_info); | 59 | |
71 | if ((cred.cr_uid)) { | 60 | for (i = 0; i < rqgi->ngroups; i++) { |
72 | act_as->cap_effective = | 61 | if (!GROUP_AT(rqgi, i)) |
73 | cap_drop_nfsd_set(act_as->cap_effective); | 62 | GROUP_AT(gi, i) = exp->ex_anon_gid; |
63 | else | ||
64 | GROUP_AT(gi, i) = GROUP_AT(rqgi, i); | ||
65 | } | ||
74 | } else { | 66 | } else { |
75 | act_as->cap_effective = | 67 | gi = get_group_info(rqgi); |
76 | cap_raise_nfsd_set(act_as->cap_effective, | ||
77 | act_as->cap_permitted); | ||
78 | } | 68 | } |
69 | |||
70 | if (new->fsuid == (uid_t) -1) | ||
71 | new->fsuid = exp->ex_anon_uid; | ||
72 | if (new->fsgid == (gid_t) -1) | ||
73 | new->fsgid = exp->ex_anon_gid; | ||
74 | |||
75 | ret = set_groups(new, gi); | ||
76 | put_group_info(gi); | ||
77 | if (!ret) | ||
78 | goto error; | ||
79 | |||
80 | if (new->uid) | ||
81 | new->cap_effective = cap_drop_nfsd_set(new->cap_effective); | ||
82 | else | ||
83 | new->cap_effective = cap_raise_nfsd_set(new->cap_effective, | ||
84 | new->cap_permitted); | ||
85 | return commit_creds(new); | ||
86 | |||
87 | oom: | ||
88 | ret = -ENOMEM; | ||
89 | error: | ||
90 | abort_creds(new); | ||
79 | return ret; | 91 | return ret; |
80 | } | 92 | } |
81 | 93 | ||
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 632a50b4b371..9371ea12d7fa 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c | |||
@@ -54,20 +54,26 @@ | |||
54 | static struct path rec_dir; | 54 | static struct path rec_dir; |
55 | static int rec_dir_init = 0; | 55 | static int rec_dir_init = 0; |
56 | 56 | ||
57 | static void | 57 | static int |
58 | nfs4_save_user(uid_t *saveuid, gid_t *savegid) | 58 | nfs4_save_creds(const struct cred **original_creds) |
59 | { | 59 | { |
60 | *saveuid = current->cred->fsuid; | 60 | struct cred *new; |
61 | *savegid = current->cred->fsgid; | 61 | |
62 | current->cred->fsuid = 0; | 62 | new = prepare_creds(); |
63 | current->cred->fsgid = 0; | 63 | if (!new) |
64 | return -ENOMEM; | ||
65 | |||
66 | new->fsuid = 0; | ||
67 | new->fsgid = 0; | ||
68 | *original_creds = override_creds(new); | ||
69 | put_cred(new); | ||
70 | return 0; | ||
64 | } | 71 | } |
65 | 72 | ||
66 | static void | 73 | static void |
67 | nfs4_reset_user(uid_t saveuid, gid_t savegid) | 74 | nfs4_reset_creds(const struct cred *original) |
68 | { | 75 | { |
69 | current->cred->fsuid = saveuid; | 76 | revert_creds(original); |
70 | current->cred->fsgid = savegid; | ||
71 | } | 77 | } |
72 | 78 | ||
73 | static void | 79 | static void |
@@ -129,10 +135,9 @@ nfsd4_sync_rec_dir(void) | |||
129 | int | 135 | int |
130 | nfsd4_create_clid_dir(struct nfs4_client *clp) | 136 | nfsd4_create_clid_dir(struct nfs4_client *clp) |
131 | { | 137 | { |
138 | const struct cred *original_cred; | ||
132 | char *dname = clp->cl_recdir; | 139 | char *dname = clp->cl_recdir; |
133 | struct dentry *dentry; | 140 | struct dentry *dentry; |
134 | uid_t uid; | ||
135 | gid_t gid; | ||
136 | int status; | 141 | int status; |
137 | 142 | ||
138 | dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname); | 143 | dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname); |
@@ -140,7 +145,9 @@ nfsd4_create_clid_dir(struct nfs4_client *clp) | |||
140 | if (!rec_dir_init || clp->cl_firststate) | 145 | if (!rec_dir_init || clp->cl_firststate) |
141 | return 0; | 146 | return 0; |
142 | 147 | ||
143 | nfs4_save_user(&uid, &gid); | 148 | status = nfs4_save_creds(&original_cred); |
149 | if (status < 0) | ||
150 | return status; | ||
144 | 151 | ||
145 | /* lock the parent */ | 152 | /* lock the parent */ |
146 | mutex_lock(&rec_dir.dentry->d_inode->i_mutex); | 153 | mutex_lock(&rec_dir.dentry->d_inode->i_mutex); |
@@ -168,7 +175,7 @@ out_unlock: | |||
168 | clp->cl_firststate = 1; | 175 | clp->cl_firststate = 1; |
169 | nfsd4_sync_rec_dir(); | 176 | nfsd4_sync_rec_dir(); |
170 | } | 177 | } |
171 | nfs4_reset_user(uid, gid); | 178 | nfs4_reset_creds(original_cred); |
172 | dprintk("NFSD: nfsd4_create_clid_dir returns %d\n", status); | 179 | dprintk("NFSD: nfsd4_create_clid_dir returns %d\n", status); |
173 | return status; | 180 | return status; |
174 | } | 181 | } |
@@ -211,20 +218,21 @@ nfsd4_build_dentrylist(void *arg, const char *name, int namlen, | |||
211 | static int | 218 | static int |
212 | nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f) | 219 | nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f) |
213 | { | 220 | { |
221 | const struct cred *original_cred; | ||
214 | struct file *filp; | 222 | struct file *filp; |
215 | struct dentry_list_arg dla = { | 223 | struct dentry_list_arg dla = { |
216 | .parent = dir, | 224 | .parent = dir, |
217 | }; | 225 | }; |
218 | struct list_head *dentries = &dla.dentries; | 226 | struct list_head *dentries = &dla.dentries; |
219 | struct dentry_list *child; | 227 | struct dentry_list *child; |
220 | uid_t uid; | ||
221 | gid_t gid; | ||
222 | int status; | 228 | int status; |
223 | 229 | ||
224 | if (!rec_dir_init) | 230 | if (!rec_dir_init) |
225 | return 0; | 231 | return 0; |
226 | 232 | ||
227 | nfs4_save_user(&uid, &gid); | 233 | status = nfs4_save_creds(&original_cred); |
234 | if (status < 0) | ||
235 | return status; | ||
228 | 236 | ||
229 | filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY, | 237 | filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY, |
230 | current_cred()); | 238 | current_cred()); |
@@ -250,7 +258,7 @@ out: | |||
250 | dput(child->dentry); | 258 | dput(child->dentry); |
251 | kfree(child); | 259 | kfree(child); |
252 | } | 260 | } |
253 | nfs4_reset_user(uid, gid); | 261 | nfs4_reset_creds(original_cred); |
254 | return status; | 262 | return status; |
255 | } | 263 | } |
256 | 264 | ||
@@ -312,8 +320,7 @@ out: | |||
312 | void | 320 | void |
313 | nfsd4_remove_clid_dir(struct nfs4_client *clp) | 321 | nfsd4_remove_clid_dir(struct nfs4_client *clp) |
314 | { | 322 | { |
315 | uid_t uid; | 323 | const struct cred *original_cred; |
316 | gid_t gid; | ||
317 | int status; | 324 | int status; |
318 | 325 | ||
319 | if (!rec_dir_init || !clp->cl_firststate) | 326 | if (!rec_dir_init || !clp->cl_firststate) |
@@ -323,9 +330,13 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp) | |||
323 | if (status) | 330 | if (status) |
324 | goto out; | 331 | goto out; |
325 | clp->cl_firststate = 0; | 332 | clp->cl_firststate = 0; |
326 | nfs4_save_user(&uid, &gid); | 333 | |
334 | status = nfs4_save_creds(&original_cred); | ||
335 | if (status < 0) | ||
336 | goto out; | ||
337 | |||
327 | status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1); | 338 | status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1); |
328 | nfs4_reset_user(uid, gid); | 339 | nfs4_reset_creds(original_cred); |
329 | if (status == 0) | 340 | if (status == 0) |
330 | nfsd4_sync_rec_dir(); | 341 | nfsd4_sync_rec_dir(); |
331 | mnt_drop_write(rec_dir.mnt); | 342 | mnt_drop_write(rec_dir.mnt); |
@@ -402,16 +413,21 @@ nfsd4_recdir_load(void) { | |||
402 | void | 413 | void |
403 | nfsd4_init_recdir(char *rec_dirname) | 414 | nfsd4_init_recdir(char *rec_dirname) |
404 | { | 415 | { |
405 | uid_t uid = 0; | 416 | const struct cred *original_cred; |
406 | gid_t gid = 0; | 417 | int status; |
407 | int status; | ||
408 | 418 | ||
409 | printk("NFSD: Using %s as the NFSv4 state recovery directory\n", | 419 | printk("NFSD: Using %s as the NFSv4 state recovery directory\n", |
410 | rec_dirname); | 420 | rec_dirname); |
411 | 421 | ||
412 | BUG_ON(rec_dir_init); | 422 | BUG_ON(rec_dir_init); |
413 | 423 | ||
414 | nfs4_save_user(&uid, &gid); | 424 | status = nfs4_save_creds(&original_cred); |
425 | if (status < 0) { | ||
426 | printk("NFSD: Unable to change credentials to find recovery" | ||
427 | " directory: error %d\n", | ||
428 | status); | ||
429 | return; | ||
430 | } | ||
415 | 431 | ||
416 | status = kern_path(rec_dirname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, | 432 | status = kern_path(rec_dirname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, |
417 | &rec_dir); | 433 | &rec_dir); |
@@ -421,7 +437,7 @@ nfsd4_init_recdir(char *rec_dirname) | |||
421 | 437 | ||
422 | if (!status) | 438 | if (!status) |
423 | rec_dir_init = 1; | 439 | rec_dir_init = 1; |
424 | nfs4_reset_user(uid, gid); | 440 | nfs4_reset_creds(original_cred); |
425 | } | 441 | } |
426 | 442 | ||
427 | void | 443 | void |
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index e67cfaea0865..f0da7d9c3a92 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c | |||
@@ -186,9 +186,14 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp) | |||
186 | * access control settings being in effect, we cannot | 186 | * access control settings being in effect, we cannot |
187 | * fix that case easily. | 187 | * fix that case easily. |
188 | */ | 188 | */ |
189 | current->cred->cap_effective = | 189 | struct cred *new = prepare_creds(); |
190 | cap_raise_nfsd_set(current->cred->cap_effective, | 190 | if (!new) |
191 | current->cred->cap_permitted); | 191 | return nfserrno(-ENOMEM); |
192 | new->cap_effective = | ||
193 | cap_raise_nfsd_set(new->cap_effective, | ||
194 | new->cap_permitted); | ||
195 | put_cred(override_creds(new)); | ||
196 | put_cred(new); | ||
192 | } else { | 197 | } else { |
193 | error = nfsd_setuser_and_check_port(rqstp, exp); | 198 | error = nfsd_setuser_and_check_port(rqstp, exp); |
194 | if (error) | 199 | if (error) |
@@ -425,30 +425,33 @@ out: | |||
425 | */ | 425 | */ |
426 | asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) | 426 | asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) |
427 | { | 427 | { |
428 | struct cred *cred = current->cred; | 428 | const struct cred *old_cred; |
429 | struct cred *override_cred; | ||
429 | struct path path; | 430 | struct path path; |
430 | struct inode *inode; | 431 | struct inode *inode; |
431 | int old_fsuid, old_fsgid; | ||
432 | kernel_cap_t uninitialized_var(old_cap); /* !SECURE_NO_SETUID_FIXUP */ | ||
433 | int res; | 432 | int res; |
434 | 433 | ||
435 | if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ | 434 | if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ |
436 | return -EINVAL; | 435 | return -EINVAL; |
437 | 436 | ||
438 | old_fsuid = cred->fsuid; | 437 | override_cred = prepare_creds(); |
439 | old_fsgid = cred->fsgid; | 438 | if (!override_cred) |
439 | return -ENOMEM; | ||
440 | 440 | ||
441 | cred->fsuid = cred->uid; | 441 | override_cred->fsuid = override_cred->uid; |
442 | cred->fsgid = cred->gid; | 442 | override_cred->fsgid = override_cred->gid; |
443 | 443 | ||
444 | if (!issecure(SECURE_NO_SETUID_FIXUP)) { | 444 | if (!issecure(SECURE_NO_SETUID_FIXUP)) { |
445 | /* Clear the capabilities if we switch to a non-root user */ | 445 | /* Clear the capabilities if we switch to a non-root user */ |
446 | if (current->cred->uid) | 446 | if (override_cred->uid) |
447 | old_cap = cap_set_effective(__cap_empty_set); | 447 | cap_clear(override_cred->cap_effective); |
448 | else | 448 | else |
449 | old_cap = cap_set_effective(cred->cap_permitted); | 449 | override_cred->cap_effective = |
450 | override_cred->cap_permitted; | ||
450 | } | 451 | } |
451 | 452 | ||
453 | old_cred = override_creds(override_cred); | ||
454 | |||
452 | res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path); | 455 | res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path); |
453 | if (res) | 456 | if (res) |
454 | goto out; | 457 | goto out; |
@@ -485,12 +488,8 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) | |||
485 | out_path_release: | 488 | out_path_release: |
486 | path_put(&path); | 489 | path_put(&path); |
487 | out: | 490 | out: |
488 | cred->fsuid = old_fsuid; | 491 | revert_creds(old_cred); |
489 | cred->fsgid = old_fsgid; | 492 | put_cred(override_cred); |
490 | |||
491 | if (!issecure(SECURE_NO_SETUID_FIXUP)) | ||
492 | cap_set_effective(old_cap); | ||
493 | |||
494 | return res; | 493 | return res; |
495 | } | 494 | } |
496 | 495 | ||