Commit f98c4469 authored by Linus Torvalds's avatar Linus Torvalds

Add 'mode' argument to vfs_symlink.

Right now we ignore it, but we need to pass this down
to the low-level filesystems if we want to ever make
knfsd create symlinks with different permissions correctly.
parent 4e82b2d8
......@@ -204,7 +204,7 @@ hwgfs_mk_symlink(
error = hwgfs_decode(dir, name, 0, &parent_inode, &dentry);
if (likely(!error)) {
error = vfs_symlink(parent_inode, dentry, link);
error = vfs_symlink(parent_inode, dentry, link, S_IALLUGO);
dentry->d_fsdata = info;
if (handle)
*handle = dentry;
......
......@@ -1759,7 +1759,7 @@ asmlinkage long sys_unlink(const char __user * pathname)
goto exit2;
}
int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, int mode)
{
int error = may_create(dir, dentry, NULL);
......@@ -1803,7 +1803,7 @@ asmlinkage long sys_symlink(const char __user * oldname, const char __user * new
dentry = lookup_create(&nd, 0);
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
error = vfs_symlink(nd.dentry->d_inode, dentry, from);
error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO);
dput(dentry);
}
up(&nd.dentry->d_inode->i_sem);
......
......@@ -1184,6 +1184,7 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
{
struct dentry *dentry, *dnew;
int err, cerr;
umode_t mode;
err = nfserr_noent;
if (!flen || !plen)
......@@ -1202,6 +1203,11 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
if (IS_ERR(dnew))
goto out_nfserr;
mode = S_IALLUGO;
/* Only the MODE ATTRibute is even vaguely meaningful */
if (iap && (iap->ia_valid & ATTR_MODE))
mode = iap->ia_mode & S_IALLUGO;
if (unlikely(path[plen] != 0)) {
char *path_alloced = kmalloc(plen+1, GFP_KERNEL);
if (path_alloced == NULL)
......@@ -1209,30 +1215,15 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
else {
strncpy(path_alloced, path, plen);
path_alloced[plen] = 0;
err = vfs_symlink(dentry->d_inode, dnew, path_alloced);
err = vfs_symlink(dentry->d_inode, dnew, path_alloced, mode);
kfree(path_alloced);
}
} else
err = vfs_symlink(dentry->d_inode, dnew, path);
err = vfs_symlink(dentry->d_inode, dnew, path, mode);
if (!err) {
if (EX_ISSYNC(fhp->fh_export))
nfsd_sync_dir(dentry);
if (iap) {
iap->ia_valid &= ATTR_MODE; /* Only the MODE ATTRibute is
* even vaguely meaningful */
if (iap->ia_valid) {
iap->ia_valid |= ATTR_CTIME;
iap->ia_mode = (iap->ia_mode&S_IALLUGO)
| S_IFLNK;
if (notify_change(dnew, iap)==0)
if (EX_ISSYNC(fhp->fh_export))
write_inode_now(dentry->d_inode, 1);
/* errors from notify_change are not
* propagated to client
*/
}
}
} else
err = nfserrno(err);
fh_unlock(fhp);
......
......@@ -795,7 +795,7 @@ static inline void unlock_super(struct super_block * sb)
extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *);
extern int vfs_mkdir(struct inode *, struct dentry *, int);
extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t);
extern int vfs_symlink(struct inode *, struct dentry *, const char *);
extern int vfs_symlink(struct inode *, struct dentry *, const char *, int);
extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
extern int vfs_rmdir(struct inode *, struct dentry *);
extern int vfs_unlink(struct inode *, struct dentry *);
......
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