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( ...@@ -204,7 +204,7 @@ hwgfs_mk_symlink(
error = hwgfs_decode(dir, name, 0, &parent_inode, &dentry); error = hwgfs_decode(dir, name, 0, &parent_inode, &dentry);
if (likely(!error)) { if (likely(!error)) {
error = vfs_symlink(parent_inode, dentry, link); error = vfs_symlink(parent_inode, dentry, link, S_IALLUGO);
dentry->d_fsdata = info; dentry->d_fsdata = info;
if (handle) if (handle)
*handle = dentry; *handle = dentry;
......
...@@ -1759,7 +1759,7 @@ asmlinkage long sys_unlink(const char __user * pathname) ...@@ -1759,7 +1759,7 @@ asmlinkage long sys_unlink(const char __user * pathname)
goto exit2; 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); int error = may_create(dir, dentry, NULL);
...@@ -1803,7 +1803,7 @@ asmlinkage long sys_symlink(const char __user * oldname, const char __user * new ...@@ -1803,7 +1803,7 @@ asmlinkage long sys_symlink(const char __user * oldname, const char __user * new
dentry = lookup_create(&nd, 0); dentry = lookup_create(&nd, 0);
error = PTR_ERR(dentry); error = PTR_ERR(dentry);
if (!IS_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); dput(dentry);
} }
up(&nd.dentry->d_inode->i_sem); up(&nd.dentry->d_inode->i_sem);
......
...@@ -1184,6 +1184,7 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, ...@@ -1184,6 +1184,7 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
{ {
struct dentry *dentry, *dnew; struct dentry *dentry, *dnew;
int err, cerr; int err, cerr;
umode_t mode;
err = nfserr_noent; err = nfserr_noent;
if (!flen || !plen) if (!flen || !plen)
...@@ -1202,6 +1203,11 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, ...@@ -1202,6 +1203,11 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
if (IS_ERR(dnew)) if (IS_ERR(dnew))
goto out_nfserr; 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)) { if (unlikely(path[plen] != 0)) {
char *path_alloced = kmalloc(plen+1, GFP_KERNEL); char *path_alloced = kmalloc(plen+1, GFP_KERNEL);
if (path_alloced == NULL) if (path_alloced == NULL)
...@@ -1209,30 +1215,15 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, ...@@ -1209,30 +1215,15 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
else { else {
strncpy(path_alloced, path, plen); strncpy(path_alloced, path, plen);
path_alloced[plen] = 0; 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); kfree(path_alloced);
} }
} else } else
err = vfs_symlink(dentry->d_inode, dnew, path); err = vfs_symlink(dentry->d_inode, dnew, path, mode);
if (!err) { if (!err) {
if (EX_ISSYNC(fhp->fh_export)) if (EX_ISSYNC(fhp->fh_export))
nfsd_sync_dir(dentry); 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 } else
err = nfserrno(err); err = nfserrno(err);
fh_unlock(fhp); fh_unlock(fhp);
......
...@@ -795,7 +795,7 @@ static inline void unlock_super(struct super_block * sb) ...@@ -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_create(struct inode *, struct dentry *, int, struct nameidata *);
extern int vfs_mkdir(struct inode *, struct dentry *, int); extern int vfs_mkdir(struct inode *, struct dentry *, int);
extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t); 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_link(struct dentry *, struct inode *, struct dentry *);
extern int vfs_rmdir(struct inode *, struct dentry *); extern int vfs_rmdir(struct inode *, struct dentry *);
extern int vfs_unlink(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