aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c66
1 files changed, 42 insertions, 24 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 4acdac043b6b..8dc2b038d5d9 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -790,7 +790,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
790 790
791 inode = nd->dentry->d_inode; 791 inode = nd->dentry->d_inode;
792 if (nd->depth) 792 if (nd->depth)
793 lookup_flags = LOOKUP_FOLLOW; 793 lookup_flags = LOOKUP_FOLLOW | (nd->flags & LOOKUP_CONTINUE);
794 794
795 /* At this point we know we have a real path component. */ 795 /* At this point we know we have a real path component. */
796 for(;;) { 796 for(;;) {
@@ -885,7 +885,8 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
885last_with_slashes: 885last_with_slashes:
886 lookup_flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY; 886 lookup_flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
887last_component: 887last_component:
888 nd->flags &= ~LOOKUP_CONTINUE; 888 /* Clear LOOKUP_CONTINUE iff it was previously unset */
889 nd->flags &= lookup_flags | ~LOOKUP_CONTINUE;
889 if (lookup_flags & LOOKUP_PARENT) 890 if (lookup_flags & LOOKUP_PARENT)
890 goto lookup_parent; 891 goto lookup_parent;
891 if (this.name[0] == '.') switch (this.len) { 892 if (this.name[0] == '.') switch (this.len) {
@@ -1069,6 +1070,8 @@ static int fastcall do_path_lookup(int dfd, const char *name,
1069 unsigned int flags, struct nameidata *nd) 1070 unsigned int flags, struct nameidata *nd)
1070{ 1071{
1071 int retval = 0; 1072 int retval = 0;
1073 int fput_needed;
1074 struct file *file;
1072 1075
1073 nd->last_type = LAST_ROOT; /* if there are only slashes... */ 1076 nd->last_type = LAST_ROOT; /* if there are only slashes... */
1074 nd->flags = flags; 1077 nd->flags = flags;
@@ -1090,29 +1093,22 @@ static int fastcall do_path_lookup(int dfd, const char *name,
1090 nd->mnt = mntget(current->fs->pwdmnt); 1093 nd->mnt = mntget(current->fs->pwdmnt);
1091 nd->dentry = dget(current->fs->pwd); 1094 nd->dentry = dget(current->fs->pwd);
1092 } else { 1095 } else {
1093 struct file *file;
1094 int fput_needed;
1095 struct dentry *dentry; 1096 struct dentry *dentry;
1096 1097
1097 file = fget_light(dfd, &fput_needed); 1098 file = fget_light(dfd, &fput_needed);
1098 if (!file) { 1099 retval = -EBADF;
1099 retval = -EBADF; 1100 if (!file)
1100 goto out_fail; 1101 goto unlock_fail;
1101 }
1102 1102
1103 dentry = file->f_dentry; 1103 dentry = file->f_dentry;
1104 1104
1105 if (!S_ISDIR(dentry->d_inode->i_mode)) { 1105 retval = -ENOTDIR;
1106 retval = -ENOTDIR; 1106 if (!S_ISDIR(dentry->d_inode->i_mode))
1107 fput_light(file, fput_needed); 1107 goto fput_unlock_fail;
1108 goto out_fail;
1109 }
1110 1108
1111 retval = file_permission(file, MAY_EXEC); 1109 retval = file_permission(file, MAY_EXEC);
1112 if (retval) { 1110 if (retval)
1113 fput_light(file, fput_needed); 1111 goto fput_unlock_fail;
1114 goto out_fail;
1115 }
1116 1112
1117 nd->mnt = mntget(file->f_vfsmnt); 1113 nd->mnt = mntget(file->f_vfsmnt);
1118 nd->dentry = dget(dentry); 1114 nd->dentry = dget(dentry);
@@ -1123,10 +1119,17 @@ static int fastcall do_path_lookup(int dfd, const char *name,
1123 current->total_link_count = 0; 1119 current->total_link_count = 0;
1124 retval = link_path_walk(name, nd); 1120 retval = link_path_walk(name, nd);
1125out: 1121out:
1126 if (unlikely(current->audit_context 1122 if (likely(retval == 0)) {
1127 && nd && nd->dentry && nd->dentry->d_inode)) 1123 if (unlikely(current->audit_context && nd && nd->dentry &&
1124 nd->dentry->d_inode))
1128 audit_inode(name, nd->dentry->d_inode, flags); 1125 audit_inode(name, nd->dentry->d_inode, flags);
1129out_fail: 1126 }
1127 return retval;
1128
1129fput_unlock_fail:
1130 fput_light(file, fput_needed);
1131unlock_fail:
1132 read_unlock(&current->fs->lock);
1130 return retval; 1133 return retval;
1131} 1134}
1132 1135
@@ -1161,6 +1164,7 @@ static int __path_lookup_intent_open(int dfd, const char *name,
1161 1164
1162/** 1165/**
1163 * path_lookup_open - lookup a file path with open intent 1166 * path_lookup_open - lookup a file path with open intent
1167 * @dfd: the directory to use as base, or AT_FDCWD
1164 * @name: pointer to file name 1168 * @name: pointer to file name
1165 * @lookup_flags: lookup intent flags 1169 * @lookup_flags: lookup intent flags
1166 * @nd: pointer to nameidata 1170 * @nd: pointer to nameidata
@@ -1175,6 +1179,7 @@ int path_lookup_open(int dfd, const char *name, unsigned int lookup_flags,
1175 1179
1176/** 1180/**
1177 * path_lookup_create - lookup a file path with open + create intent 1181 * path_lookup_create - lookup a file path with open + create intent
1182 * @dfd: the directory to use as base, or AT_FDCWD
1178 * @name: pointer to file name 1183 * @name: pointer to file name
1179 * @lookup_flags: lookup intent flags 1184 * @lookup_flags: lookup intent flags
1180 * @nd: pointer to nameidata 1185 * @nd: pointer to nameidata
@@ -2219,13 +2224,17 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
2219 * and other special files. --ADM 2224 * and other special files. --ADM
2220 */ 2225 */
2221asmlinkage long sys_linkat(int olddfd, const char __user *oldname, 2226asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
2222 int newdfd, const char __user *newname) 2227 int newdfd, const char __user *newname,
2228 int flags)
2223{ 2229{
2224 struct dentry *new_dentry; 2230 struct dentry *new_dentry;
2225 struct nameidata nd, old_nd; 2231 struct nameidata nd, old_nd;
2226 int error; 2232 int error;
2227 char * to; 2233 char * to;
2228 2234
2235 if (flags != 0)
2236 return -EINVAL;
2237
2229 to = getname(newname); 2238 to = getname(newname);
2230 if (IS_ERR(to)) 2239 if (IS_ERR(to))
2231 return PTR_ERR(to); 2240 return PTR_ERR(to);
@@ -2258,7 +2267,7 @@ exit:
2258 2267
2259asmlinkage long sys_link(const char __user *oldname, const char __user *newname) 2268asmlinkage long sys_link(const char __user *oldname, const char __user *newname)
2260{ 2269{
2261 return sys_linkat(AT_FDCWD, oldname, AT_FDCWD, newname); 2270 return sys_linkat(AT_FDCWD, oldname, AT_FDCWD, newname, 0);
2262} 2271}
2263 2272
2264/* 2273/*
@@ -2604,13 +2613,15 @@ void page_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
2604 } 2613 }
2605} 2614}
2606 2615
2607int page_symlink(struct inode *inode, const char *symname, int len) 2616int __page_symlink(struct inode *inode, const char *symname, int len,
2617 gfp_t gfp_mask)
2608{ 2618{
2609 struct address_space *mapping = inode->i_mapping; 2619 struct address_space *mapping = inode->i_mapping;
2610 struct page *page = grab_cache_page(mapping, 0); 2620 struct page *page;
2611 int err = -ENOMEM; 2621 int err = -ENOMEM;
2612 char *kaddr; 2622 char *kaddr;
2613 2623
2624 page = find_or_create_page(mapping, 0, gfp_mask);
2614 if (!page) 2625 if (!page)
2615 goto fail; 2626 goto fail;
2616 err = mapping->a_ops->prepare_write(NULL, page, 0, len-1); 2627 err = mapping->a_ops->prepare_write(NULL, page, 0, len-1);
@@ -2645,6 +2656,12 @@ fail:
2645 return err; 2656 return err;
2646} 2657}
2647 2658
2659int page_symlink(struct inode *inode, const char *symname, int len)
2660{
2661 return __page_symlink(inode, symname, len,
2662 mapping_gfp_mask(inode->i_mapping));
2663}
2664
2648struct inode_operations page_symlink_inode_operations = { 2665struct inode_operations page_symlink_inode_operations = {
2649 .readlink = generic_readlink, 2666 .readlink = generic_readlink,
2650 .follow_link = page_follow_link_light, 2667 .follow_link = page_follow_link_light,
@@ -2663,6 +2680,7 @@ EXPORT_SYMBOL(lookup_one_len);
2663EXPORT_SYMBOL(page_follow_link_light); 2680EXPORT_SYMBOL(page_follow_link_light);
2664EXPORT_SYMBOL(page_put_link); 2681EXPORT_SYMBOL(page_put_link);
2665EXPORT_SYMBOL(page_readlink); 2682EXPORT_SYMBOL(page_readlink);
2683EXPORT_SYMBOL(__page_symlink);
2666EXPORT_SYMBOL(page_symlink); 2684EXPORT_SYMBOL(page_symlink);
2667EXPORT_SYMBOL(page_symlink_inode_operations); 2685EXPORT_SYMBOL(page_symlink_inode_operations);
2668EXPORT_SYMBOL(path_lookup); 2686EXPORT_SYMBOL(path_lookup);