Commit 745ca2475a6ac596e3d8d37c2759c0fbe2586227

Authored by David Howells
Committed by James Morris
1 parent 88e67f3b88

CRED: Pass credentials through dentry_open()

Pass credentials through dentry_open() so that the COW creds patch can have
SELinux's flush_unauthorized_files() pass the appropriate creds back to itself
when it opens its null chardev.

The security_dentry_open() call also now takes a creds pointer, as does the
dentry_open hook in struct security_operations.

Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: James Morris <jmorris@namei.org>
Signed-off-by: James Morris <jmorris@namei.org>

Showing 19 changed files with 67 additions and 40 deletions Side-by-side Diff

arch/powerpc/platforms/cell/spufs/inode.c
... ... @@ -323,7 +323,7 @@
323 323 goto out;
324 324 }
325 325  
326   - filp = dentry_open(dentry, mnt, O_RDONLY);
  326 + filp = dentry_open(dentry, mnt, O_RDONLY, current_cred());
327 327 if (IS_ERR(filp)) {
328 328 put_unused_fd(ret);
329 329 ret = PTR_ERR(filp);
... ... @@ -562,7 +562,7 @@
562 562 goto out;
563 563 }
564 564  
565   - filp = dentry_open(dentry, mnt, O_RDONLY);
  565 + filp = dentry_open(dentry, mnt, O_RDONLY, current_cred());
566 566 if (IS_ERR(filp)) {
567 567 put_unused_fd(ret);
568 568 ret = PTR_ERR(filp);
arch/um/drivers/mconsole_kern.c
... ... @@ -159,7 +159,8 @@
159 159 goto out_kill;
160 160 }
161 161  
162   - file = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY);
  162 + file = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY,
  163 + current_cred());
163 164 if (IS_ERR(file)) {
164 165 mconsole_reply(req, "Failed to open file", 1, 0);
165 166 goto out_kill;
fs/autofs4/dev-ioctl.c
... ... @@ -307,7 +307,8 @@
307 307 goto out;
308 308 }
309 309  
310   - filp = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY);
  310 + filp = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY,
  311 + current_cred());
311 312 if (IS_ERR(filp)) {
312 313 err = PTR_ERR(filp);
313 314 goto out;
fs/ecryptfs/ecryptfs_kernel.h
... ... @@ -691,7 +691,8 @@
691 691 void ecryptfs_destroy_kthread(void);
692 692 int ecryptfs_privileged_open(struct file **lower_file,
693 693 struct dentry *lower_dentry,
694   - struct vfsmount *lower_mnt);
  694 + struct vfsmount *lower_mnt,
  695 + const struct cred *cred);
695 696 int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry);
696 697  
697 698 #endif /* #ifndef ECRYPTFS_KERNEL_H */
fs/ecryptfs/kthread.c
... ... @@ -73,7 +73,7 @@
73 73 mntget(req->lower_mnt);
74 74 (*req->lower_file) = dentry_open(
75 75 req->lower_dentry, req->lower_mnt,
76   - (O_RDWR | O_LARGEFILE));
  76 + (O_RDWR | O_LARGEFILE), current_cred());
77 77 req->flags |= ECRYPTFS_REQ_PROCESSED;
78 78 }
79 79 wake_up(&req->wait);
... ... @@ -132,7 +132,8 @@
132 132 */
133 133 int ecryptfs_privileged_open(struct file **lower_file,
134 134 struct dentry *lower_dentry,
135   - struct vfsmount *lower_mnt)
  135 + struct vfsmount *lower_mnt,
  136 + const struct cred *cred)
136 137 {
137 138 struct ecryptfs_open_req *req;
138 139 int rc = 0;
... ... @@ -143,7 +144,7 @@
143 144 dget(lower_dentry);
144 145 mntget(lower_mnt);
145 146 (*lower_file) = dentry_open(lower_dentry, lower_mnt,
146   - (O_RDWR | O_LARGEFILE));
  147 + (O_RDWR | O_LARGEFILE), cred);
147 148 if (!IS_ERR(*lower_file))
148 149 goto out;
149 150 req = kmem_cache_alloc(ecryptfs_open_req_cache, GFP_KERNEL);
... ... @@ -184,7 +185,7 @@
184 185 dget(lower_dentry);
185 186 mntget(lower_mnt);
186 187 (*lower_file) = dentry_open(lower_dentry, lower_mnt,
187   - (O_RDONLY | O_LARGEFILE));
  188 + (O_RDONLY | O_LARGEFILE), cred);
188 189 if (IS_ERR(*lower_file)) {
189 190 rc = PTR_ERR(*req->lower_file);
190 191 (*lower_file) = NULL;
... ... @@ -115,6 +115,7 @@
115 115 */
116 116 int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
117 117 {
  118 + const struct cred *cred = current_cred();
118 119 struct ecryptfs_inode_info *inode_info =
119 120 ecryptfs_inode_to_private(ecryptfs_dentry->d_inode);
120 121 int rc = 0;
... ... @@ -127,7 +128,7 @@
127 128  
128 129 lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
129 130 rc = ecryptfs_privileged_open(&inode_info->lower_file,
130   - lower_dentry, lower_mnt);
  131 + lower_dentry, lower_mnt, cred);
131 132 if (rc || IS_ERR(inode_info->lower_file)) {
132 133 printk(KERN_ERR "Error opening lower persistent file "
133 134 "for lower_dentry [0x%p] and lower_mnt [0x%p]; "
... ... @@ -14,6 +14,7 @@
14 14 #include <linux/module.h>
15 15 #include <linux/mount.h>
16 16 #include <linux/namei.h>
  17 +#include <linux/sched.h>
17 18  
18 19 #define dprintk(fmt, args...) do{}while(0)
19 20  
... ... @@ -249,6 +250,7 @@
249 250 static int get_name(struct vfsmount *mnt, struct dentry *dentry,
250 251 char *name, struct dentry *child)
251 252 {
  253 + const struct cred *cred = current_cred();
252 254 struct inode *dir = dentry->d_inode;
253 255 int error;
254 256 struct file *file;
... ... @@ -263,7 +265,7 @@
263 265 /*
264 266 * Open the directory ...
265 267 */
266   - file = dentry_open(dget(dentry), mntget(mnt), O_RDONLY);
  268 + file = dentry_open(dget(dentry), mntget(mnt), O_RDONLY, cred);
267 269 error = PTR_ERR(file);
268 270 if (IS_ERR(file))
269 271 goto out;
... ... @@ -426,6 +426,7 @@
426 426  
427 427 static int hppfs_open(struct inode *inode, struct file *file)
428 428 {
  429 + const struct cred *cred = current_cred();
429 430 struct hppfs_private *data;
430 431 struct vfsmount *proc_mnt;
431 432 struct dentry *proc_dentry;
... ... @@ -446,7 +447,7 @@
446 447  
447 448 /* XXX This isn't closed anywhere */
448 449 data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt),
449   - file_mode(file->f_mode));
  450 + file_mode(file->f_mode), cred);
450 451 err = PTR_ERR(data->proc_file);
451 452 if (IS_ERR(data->proc_file))
452 453 goto out_free1;
... ... @@ -489,6 +490,7 @@
489 490  
490 491 static int hppfs_dir_open(struct inode *inode, struct file *file)
491 492 {
  493 + const struct cred *cred = current_cred();
492 494 struct hppfs_private *data;
493 495 struct vfsmount *proc_mnt;
494 496 struct dentry *proc_dentry;
... ... @@ -502,7 +504,7 @@
502 504 proc_dentry = HPPFS_I(inode)->proc_dentry;
503 505 proc_mnt = inode->i_sb->s_fs_info;
504 506 data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt),
505   - file_mode(file->f_mode));
  507 + file_mode(file->f_mode), cred);
506 508 err = PTR_ERR(data->proc_file);
507 509 if (IS_ERR(data->proc_file))
508 510 goto out_free;
... ... @@ -41,7 +41,8 @@
41 41 error = may_open(&nd, MAY_WRITE, FMODE_WRITE);
42 42  
43 43 if (!error)
44   - return dentry_open(nd.path.dentry, nd.path.mnt, flags);
  44 + return dentry_open(nd.path.dentry, nd.path.mnt, flags,
  45 + current_cred());
45 46  
46 47 path_put(&nd.path);
47 48 return ERR_PTR(error);
fs/nfsd/nfs4recover.c
... ... @@ -226,7 +226,8 @@
226 226  
227 227 nfs4_save_user(&uid, &gid);
228 228  
229   - filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY);
  229 + filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY,
  230 + current_cred());
230 231 status = PTR_ERR(filp);
231 232 if (IS_ERR(filp))
232 233 goto out;
... ... @@ -671,6 +671,7 @@
671 671 nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
672 672 int access, struct file **filp)
673 673 {
  674 + const struct cred *cred = current_cred();
674 675 struct dentry *dentry;
675 676 struct inode *inode;
676 677 int flags = O_RDONLY|O_LARGEFILE;
... ... @@ -725,7 +726,7 @@
725 726 DQUOT_INIT(inode);
726 727 }
727 728 *filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_path.mnt),
728   - flags);
  729 + flags, cred);
729 730 if (IS_ERR(*filp))
730 731 host_err = PTR_ERR(*filp);
731 732 out_nfserr:
... ... @@ -783,7 +783,8 @@
783 783  
784 784 static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
785 785 int flags, struct file *f,
786   - int (*open)(struct inode *, struct file *))
  786 + int (*open)(struct inode *, struct file *),
  787 + const struct cred *cred)
787 788 {
788 789 struct inode *inode;
789 790 int error;
... ... @@ -807,7 +808,7 @@
807 808 f->f_op = fops_get(inode->i_fop);
808 809 file_move(f, &inode->i_sb->s_files);
809 810  
810   - error = security_dentry_open(f);
  811 + error = security_dentry_open(f, cred);
811 812 if (error)
812 813 goto cleanup_all;
813 814  
... ... @@ -882,6 +883,8 @@
882 883 struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
883 884 int (*open)(struct inode *, struct file *))
884 885 {
  886 + const struct cred *cred = current_cred();
  887 +
885 888 if (IS_ERR(nd->intent.open.file))
886 889 goto out;
887 890 if (IS_ERR(dentry))
... ... @@ -889,7 +892,7 @@
889 892 nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->path.mnt),
890 893 nd->intent.open.flags - 1,
891 894 nd->intent.open.file,
892   - open);
  895 + open, cred);
893 896 out:
894 897 return nd->intent.open.file;
895 898 out_err:
... ... @@ -908,6 +911,7 @@
908 911 */
909 912 struct file *nameidata_to_filp(struct nameidata *nd, int flags)
910 913 {
  914 + const struct cred *cred = current_cred();
911 915 struct file *filp;
912 916  
913 917 /* Pick up the filp from the open intent */
... ... @@ -915,7 +919,7 @@
915 919 /* Has the filesystem initialised the file for us? */
916 920 if (filp->f_path.dentry == NULL)
917 921 filp = __dentry_open(nd->path.dentry, nd->path.mnt, flags, filp,
918   - NULL);
  922 + NULL, cred);
919 923 else
920 924 path_put(&nd->path);
921 925 return filp;
... ... @@ -925,7 +929,8 @@
925 929 * dentry_open() will have done dput(dentry) and mntput(mnt) if it returns an
926 930 * error.
927 931 */
928   -struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
  932 +struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags,
  933 + const struct cred *cred)
929 934 {
930 935 int error;
931 936 struct file *f;
... ... @@ -950,7 +955,7 @@
950 955 return ERR_PTR(error);
951 956 }
952 957  
953   - return __dentry_open(dentry, mnt, flags, f, NULL);
  958 + return __dentry_open(dentry, mnt, flags, f, NULL, cred);
954 959 }
955 960 EXPORT_SYMBOL(dentry_open);
956 961  
fs/xfs/linux-2.6/xfs_ioctl.c
... ... @@ -256,6 +256,7 @@
256 256 struct file *parfilp,
257 257 struct inode *parinode)
258 258 {
  259 + const struct cred *cred = current_cred();
259 260 int error;
260 261 int new_fd;
261 262 int permflag;
... ... @@ -321,7 +322,7 @@
321 322 mntget(parfilp->f_path.mnt);
322 323  
323 324 /* Create file pointer. */
324   - filp = dentry_open(dentry, parfilp->f_path.mnt, hreq.oflags);
  325 + filp = dentry_open(dentry, parfilp->f_path.mnt, hreq.oflags, cred);
325 326 if (IS_ERR(filp)) {
326 327 put_unused_fd(new_fd);
327 328 return -XFS_ERROR(-PTR_ERR(filp));
... ... @@ -315,6 +315,7 @@
315 315 struct kstatfs;
316 316 struct vm_area_struct;
317 317 struct vfsmount;
  318 +struct cred;
318 319  
319 320 extern void __init inode_init(void);
320 321 extern void __init inode_init_early(void);
... ... @@ -1673,7 +1674,8 @@
1673 1674 extern long do_sys_open(int dfd, const char __user *filename, int flags,
1674 1675 int mode);
1675 1676 extern struct file *filp_open(const char *, int, int);
1676   -extern struct file * dentry_open(struct dentry *, struct vfsmount *, int);
  1677 +extern struct file * dentry_open(struct dentry *, struct vfsmount *, int,
  1678 + const struct cred *);
1677 1679 extern int filp_close(struct file *, fl_owner_t id);
1678 1680 extern char * getname(const char __user *);
1679 1681  
include/linux/security.h
... ... @@ -1402,7 +1402,7 @@
1402 1402 int (*file_send_sigiotask) (struct task_struct *tsk,
1403 1403 struct fown_struct *fown, int sig);
1404 1404 int (*file_receive) (struct file *file);
1405   - int (*dentry_open) (struct file *file);
  1405 + int (*dentry_open) (struct file *file, const struct cred *cred);
1406 1406  
1407 1407 int (*task_create) (unsigned long clone_flags);
1408 1408 int (*cred_alloc_security) (struct cred *cred);
... ... @@ -1658,7 +1658,7 @@
1658 1658 int security_file_send_sigiotask(struct task_struct *tsk,
1659 1659 struct fown_struct *fown, int sig);
1660 1660 int security_file_receive(struct file *file);
1661   -int security_dentry_open(struct file *file);
  1661 +int security_dentry_open(struct file *file, const struct cred *cred);
1662 1662 int security_task_create(unsigned long clone_flags);
1663 1663 int security_cred_alloc(struct cred *cred);
1664 1664 void security_cred_free(struct cred *cred);
... ... @@ -2171,7 +2171,8 @@
2171 2171 return 0;
2172 2172 }
2173 2173  
2174   -static inline int security_dentry_open(struct file *file)
  2174 +static inline int security_dentry_open(struct file *file,
  2175 + const struct cred *cred)
2175 2176 {
2176 2177 return 0;
2177 2178 }
... ... @@ -594,6 +594,7 @@
594 594 static struct file *do_create(struct dentry *dir, struct dentry *dentry,
595 595 int oflag, mode_t mode, struct mq_attr __user *u_attr)
596 596 {
  597 + const struct cred *cred = current_cred();
597 598 struct mq_attr attr;
598 599 struct file *result;
599 600 int ret;
... ... @@ -618,7 +619,7 @@
618 619 if (ret)
619 620 goto out_drop_write;
620 621  
621   - result = dentry_open(dentry, mqueue_mnt, oflag);
  622 + result = dentry_open(dentry, mqueue_mnt, oflag, cred);
622 623 /*
623 624 * dentry_open() took a persistent mnt_want_write(),
624 625 * so we can now drop this one.
625 626  
... ... @@ -637,9 +638,11 @@
637 638 /* Opens existing queue */
638 639 static struct file *do_open(struct dentry *dentry, int oflag)
639 640 {
640   -static int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE,
641   - MAY_READ | MAY_WRITE };
  641 + const struct cred *cred = current_cred();
642 642  
  643 + static const int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE,
  644 + MAY_READ | MAY_WRITE };
  645 +
643 646 if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) {
644 647 dput(dentry);
645 648 mntput(mqueue_mnt);
... ... @@ -652,7 +655,7 @@
652 655 return ERR_PTR(-EACCES);
653 656 }
654 657  
655   - return dentry_open(dentry, mqueue_mnt, oflag);
  658 + return dentry_open(dentry, mqueue_mnt, oflag, cred);
656 659 }
657 660  
658 661 asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
security/capability.c
... ... @@ -330,7 +330,7 @@
330 330 return 0;
331 331 }
332 332  
333   -static int cap_dentry_open(struct file *file)
  333 +static int cap_dentry_open(struct file *file, const struct cred *cred)
334 334 {
335 335 return 0;
336 336 }
... ... @@ -606,9 +606,9 @@
606 606 return security_ops->file_receive(file);
607 607 }
608 608  
609   -int security_dentry_open(struct file *file)
  609 +int security_dentry_open(struct file *file, const struct cred *cred)
610 610 {
611   - return security_ops->dentry_open(file);
  611 + return security_ops->dentry_open(file, cred);
612 612 }
613 613  
614 614 int security_task_create(unsigned long clone_flags)
security/selinux/hooks.c
... ... @@ -2150,9 +2150,9 @@
2150 2150 extern struct dentry *selinux_null;
2151 2151  
2152 2152 /* Derived from fs/exec.c:flush_old_files. */
2153   -static inline void flush_unauthorized_files(struct files_struct *files)
  2153 +static inline void flush_unauthorized_files(const struct cred *cred,
  2154 + struct files_struct *files)
2154 2155 {
2155   - const struct cred *cred = current_cred();
2156 2156 struct avc_audit_data ad;
2157 2157 struct file *file, *devnull = NULL;
2158 2158 struct tty_struct *tty;
... ... @@ -2222,7 +2222,10 @@
2222 2222 if (devnull) {
2223 2223 get_file(devnull);
2224 2224 } else {
2225   - devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR);
  2225 + devnull = dentry_open(
  2226 + dget(selinux_null),
  2227 + mntget(selinuxfs_mount),
  2228 + O_RDWR, cred);
2226 2229 if (IS_ERR(devnull)) {
2227 2230 devnull = NULL;
2228 2231 put_unused_fd(fd);
... ... @@ -2302,6 +2305,7 @@
2302 2305 */
2303 2306 static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm)
2304 2307 {
  2308 + const struct cred *cred = current_cred();
2305 2309 struct task_security_struct *tsec;
2306 2310 struct rlimit *rlim, *initrlim;
2307 2311 struct itimerval itimer;
... ... @@ -2321,7 +2325,7 @@
2321 2325 return;
2322 2326  
2323 2327 /* Close files for which the new task SID is not authorized. */
2324   - flush_unauthorized_files(current->files);
  2328 + flush_unauthorized_files(cred, current->files);
2325 2329  
2326 2330 /* Check whether the new SID can inherit signal state
2327 2331 from the old SID. If not, clear itimers to avoid
2328 2332  
... ... @@ -3202,9 +3206,8 @@
3202 3206 return file_has_perm(cred, file, file_to_av(file));
3203 3207 }
3204 3208  
3205   -static int selinux_dentry_open(struct file *file)
  3209 +static int selinux_dentry_open(struct file *file, const struct cred *cred)
3206 3210 {
3207   - const struct cred *cred = current_cred();
3208 3211 struct file_security_struct *fsec;
3209 3212 struct inode *inode;
3210 3213 struct inode_security_struct *isec;