mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 08:24:42 +01:00
171 lines
5 KiB
Diff
171 lines
5 KiB
Diff
From: Andreas Gruenbacher <agruen@suse.de>
|
|
Subject: Never pass a NULL nameidata to vfs_create()
|
|
|
|
---
|
|
fs/namei.c | 2 +-
|
|
fs/nfsd/vfs.c | 40 +++++++++++++++++++++++-----------------
|
|
ipc/mqueue.c | 6 +++++-
|
|
3 files changed, 29 insertions(+), 19 deletions(-)
|
|
|
|
--- a/fs/namei.c
|
|
+++ b/fs/namei.c
|
|
@@ -1546,7 +1546,7 @@ int vfs_create(struct inode *dir, struct
|
|
return -EACCES; /* shouldn't it be ENOSYS? */
|
|
mode &= S_IALLUGO;
|
|
mode |= S_IFREG;
|
|
- error = security_inode_create(dir, dentry, nd ? nd->mnt : NULL, mode);
|
|
+ error = security_inode_create(dir, dentry, nd->mnt, mode);
|
|
if (error)
|
|
return error;
|
|
DQUOT_INIT(dir);
|
|
--- a/fs/nfsd/vfs.c
|
|
+++ b/fs/nfsd/vfs.c
|
|
@@ -1121,7 +1121,8 @@ nfsd_create(struct svc_rqst *rqstp, stru
|
|
char *fname, int flen, struct iattr *iap,
|
|
int type, dev_t rdev, struct svc_fh *resfhp)
|
|
{
|
|
- struct dentry *dentry, *dchild = NULL;
|
|
+ struct nameidata nd = {};
|
|
+ struct dentry *dchild = NULL;
|
|
struct svc_export *exp;
|
|
struct inode *dirp;
|
|
__be32 err;
|
|
@@ -1138,9 +1139,10 @@ nfsd_create(struct svc_rqst *rqstp, stru
|
|
if (err)
|
|
goto out;
|
|
|
|
- dentry = fhp->fh_dentry;
|
|
+ nd.dentry = fhp->fh_dentry;
|
|
exp = fhp->fh_export;
|
|
- dirp = dentry->d_inode;
|
|
+ nd.mnt = exp->ex_mnt;
|
|
+ dirp = nd.dentry->d_inode;
|
|
|
|
err = nfserr_notdir;
|
|
if(!dirp->i_op || !dirp->i_op->lookup)
|
|
@@ -1152,7 +1154,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
|
|
if (!resfhp->fh_dentry) {
|
|
/* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */
|
|
fh_lock_nested(fhp, I_MUTEX_PARENT);
|
|
- dchild = lookup_one_len(fname, dentry, flen);
|
|
+ dchild = lookup_one_len(fname, nd.dentry, flen);
|
|
host_err = PTR_ERR(dchild);
|
|
if (IS_ERR(dchild))
|
|
goto out_nfserr;
|
|
@@ -1166,8 +1168,8 @@ nfsd_create(struct svc_rqst *rqstp, stru
|
|
/* not actually possible */
|
|
printk(KERN_ERR
|
|
"nfsd_create: parent %s/%s not locked!\n",
|
|
- dentry->d_parent->d_name.name,
|
|
- dentry->d_name.name);
|
|
+ nd.dentry->d_parent->d_name.name,
|
|
+ nd.dentry->d_name.name);
|
|
err = nfserr_io;
|
|
goto out;
|
|
}
|
|
@@ -1178,7 +1180,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
|
|
err = nfserr_exist;
|
|
if (dchild->d_inode) {
|
|
dprintk("nfsd_create: dentry %s/%s not negative!\n",
|
|
- dentry->d_name.name, dchild->d_name.name);
|
|
+ nd.dentry->d_name.name, dchild->d_name.name);
|
|
goto out;
|
|
}
|
|
|
|
@@ -1192,7 +1194,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
|
|
err = 0;
|
|
switch (type) {
|
|
case S_IFREG:
|
|
- host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
|
|
+ host_err = vfs_create(nd.dentry->d_inode, dchild, iap->ia_mode, &nd);
|
|
break;
|
|
case S_IFDIR:
|
|
host_err = vfs_mkdir(dirp, dchild, exp->ex_mnt, iap->ia_mode);
|
|
@@ -1212,7 +1214,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
|
|
goto out_nfserr;
|
|
|
|
if (EX_ISSYNC(exp)) {
|
|
- err = nfserrno(nfsd_sync_dir(dentry));
|
|
+ err = nfserrno(nfsd_sync_dir(nd.dentry));
|
|
write_inode_now(dchild->d_inode, 1);
|
|
}
|
|
|
|
@@ -1252,7 +1254,9 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
|
|
struct svc_fh *resfhp, int createmode, u32 *verifier,
|
|
int *truncp, int *created)
|
|
{
|
|
- struct dentry *dentry, *dchild = NULL;
|
|
+ struct nameidata nd = {};
|
|
+ struct dentry *dchild = NULL;
|
|
+ struct svc_export *exp;
|
|
struct inode *dirp;
|
|
__be32 err;
|
|
int host_err;
|
|
@@ -1270,8 +1274,10 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
|
|
if (err)
|
|
goto out;
|
|
|
|
- dentry = fhp->fh_dentry;
|
|
- dirp = dentry->d_inode;
|
|
+ nd.dentry = fhp->fh_dentry;
|
|
+ exp = fhp->fh_export;
|
|
+ nd.mnt = exp->ex_mnt;
|
|
+ dirp = nd.dentry->d_inode;
|
|
|
|
/* Get all the sanity checks out of the way before
|
|
* we lock the parent. */
|
|
@@ -1283,12 +1289,12 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
|
|
/*
|
|
* Compose the response file handle.
|
|
*/
|
|
- dchild = lookup_one_len(fname, dentry, flen);
|
|
+ dchild = lookup_one_len(fname, nd.dentry, flen);
|
|
host_err = PTR_ERR(dchild);
|
|
if (IS_ERR(dchild))
|
|
goto out_nfserr;
|
|
|
|
- err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
|
|
+ err = fh_compose(resfhp, exp, dchild, fhp);
|
|
if (err)
|
|
goto out;
|
|
|
|
@@ -1334,14 +1340,14 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
|
|
goto out;
|
|
}
|
|
|
|
- host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
|
|
+ host_err = vfs_create(nd.dentry->d_inode, dchild, iap->ia_mode, &nd);
|
|
if (host_err < 0)
|
|
goto out_nfserr;
|
|
if (created)
|
|
*created = 1;
|
|
|
|
- if (EX_ISSYNC(fhp->fh_export)) {
|
|
- err = nfserrno(nfsd_sync_dir(dentry));
|
|
+ if (EX_ISSYNC(exp)) {
|
|
+ err = nfserrno(nfsd_sync_dir(nd.dentry));
|
|
/* setattr will sync the child (or not) */
|
|
}
|
|
|
|
--- a/ipc/mqueue.c
|
|
+++ b/ipc/mqueue.c
|
|
@@ -604,6 +604,10 @@ static int mq_attr_ok(struct mq_attr *at
|
|
static struct file *do_create(struct dentry *dir, struct dentry *dentry,
|
|
int oflag, mode_t mode, struct mq_attr __user *u_attr)
|
|
{
|
|
+ struct nameidata nd = {
|
|
+ .dentry = dir,
|
|
+ /* Not a mounted filesystem, so set .mnt to NULL. */
|
|
+ };
|
|
struct mq_attr attr;
|
|
int ret;
|
|
|
|
@@ -619,7 +623,7 @@ static struct file *do_create(struct den
|
|
}
|
|
|
|
mode &= ~current->fs->umask;
|
|
- ret = vfs_create(dir->d_inode, dentry, mode, NULL);
|
|
+ ret = vfs_create(dir->d_inode, dentry, mode, &nd);
|
|
dentry->d_fsdata = NULL;
|
|
if (ret)
|
|
goto out;
|