Commit 66a67557 authored by Stephen D. Smalley's avatar Stephen D. Smalley Committed by Linus Torvalds

[PATCH] allocate and free security structures for private files

This patch adds a security_file_alloc call to init_private_file and
creates a close_private_file function to encapsulate the release of
private file structures.  These changes ensure that security
structures for private files will be allocated and freed
appropriately.  Per Andi Kleen's comments, the patch also renames
init_private_file to open_private_file to force updating of all
callers, since they will also need to be updated to use
close_private_file to avoid a leak of the security structure.  Per
Christoph Hellwig's comments, the patch also replaces the 'mode'
argument with a 'flags' argument, computing the f_mode from the flags,
and it explicitly tests f_op prior to dereferencing, as in
dentry_open().
parent 4f152a7e
......@@ -353,7 +353,7 @@ static int get_name(struct dentry *dentry, char *name,
/*
* Open the directory ...
*/
error = init_private_file(&file, dentry, FMODE_READ);
error = open_private_file(&file, dentry, O_RDONLY);
if (error)
goto out;
error = -EINVAL;
......@@ -381,8 +381,7 @@ static int get_name(struct dentry *dentry, char *name,
}
out_close:
if (file.f_op->release)
file.f_op->release(dir, &file);
close_private_file(&file);
out:
return error;
}
......
......@@ -93,23 +93,42 @@ struct file * get_empty_filp(void)
/*
* Clear and initialize a (private) struct file for the given dentry,
* and call the open function (if any). The caller must verify that
* inode->i_fop is not NULL.
* allocate the security structure, and call the open function (if any).
* The file should be released using close_private_file.
*/
int init_private_file(struct file *filp, struct dentry *dentry, int mode)
int open_private_file(struct file *filp, struct dentry *dentry, int flags)
{
int error;
memset(filp, 0, sizeof(*filp));
eventpoll_init_file(filp);
filp->f_mode = mode;
filp->f_flags = flags;
filp->f_mode = (flags+1) & O_ACCMODE;
atomic_set(&filp->f_count, 1);
filp->f_dentry = dentry;
filp->f_uid = current->fsuid;
filp->f_gid = current->fsgid;
filp->f_op = dentry->d_inode->i_fop;
if (filp->f_op->open)
return filp->f_op->open(dentry->d_inode, filp);
else
return 0;
error = security_file_alloc(filp);
if (!error)
if (filp->f_op && filp->f_op->open) {
error = filp->f_op->open(dentry->d_inode, filp);
if (error)
security_file_free(filp);
}
return error;
}
/*
* Release a private file by calling the release function (if any) and
* freeing the security structure.
*/
void close_private_file(struct file *file)
{
struct inode * inode = file->f_dentry->d_inode;
if (file->f_op && file->f_op->release)
file->f_op->release(inode, file);
security_file_free(file);
}
void fput(struct file * file)
......
......@@ -426,7 +426,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
{
struct dentry *dentry;
struct inode *inode;
int flags = O_RDONLY|O_LARGEFILE, mode = FMODE_READ, err;
int flags = O_RDONLY|O_LARGEFILE, err;
/*
* If we get here, then the client has already done an "open",
......@@ -463,14 +463,12 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
goto out_nfserr;
flags = O_WRONLY|O_LARGEFILE;
mode = FMODE_WRITE;
DQUOT_INIT(inode);
}
err = init_private_file(filp, dentry, mode);
err = open_private_file(filp, dentry, flags);
if (!err) {
filp->f_flags = flags;
filp->f_vfsmnt = fhp->fh_export->ex_mnt;
} else if (access & MAY_WRITE)
put_write_access(inode);
......@@ -491,8 +489,7 @@ nfsd_close(struct file *filp)
struct dentry *dentry = filp->f_dentry;
struct inode *inode = dentry->d_inode;
if (filp->f_op->release)
filp->f_op->release(inode, filp);
close_private_file(filp);
if (filp->f_mode & FMODE_WRITE)
put_write_access(inode);
}
......
......@@ -489,7 +489,10 @@ extern spinlock_t files_lock;
#define get_file(x) atomic_inc(&(x)->f_count)
#define file_count(x) atomic_read(&(x)->f_count)
extern int init_private_file(struct file *, struct dentry *, int);
/* Initialize and open a private file and allocate its security structure. */
extern int open_private_file(struct file *, struct dentry *, int);
/* Release a private file and free its security structure. */
extern void close_private_file(struct file *file);
#define MAX_NON_LFS ((1UL<<31) - 1)
......
......@@ -179,7 +179,8 @@ EXPORT_SYMBOL(mark_buffer_dirty);
EXPORT_SYMBOL(end_buffer_io_sync);
EXPORT_SYMBOL(__mark_inode_dirty);
EXPORT_SYMBOL(get_empty_filp);
EXPORT_SYMBOL(init_private_file);
EXPORT_SYMBOL(open_private_file);
EXPORT_SYMBOL(close_private_file);
EXPORT_SYMBOL(filp_open);
EXPORT_SYMBOL(filp_close);
EXPORT_SYMBOL(put_filp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment