diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2011-03-14 18:56:51 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-03-14 19:12:20 -0400 |
commit | f52e0c11305aa09ed56cad97ffc8f0cdc3d78b5d (patch) | |
tree | b04070034f8a941fe5d7e9e1b335a02784686bd5 /fs/namei.c | |
parent | 5fe0c2378884e68beb532f5890cc0e3539ac747b (diff) |
New AT_... flag: AT_EMPTY_PATH
For name_to_handle_at(2) we'll want both ...at()-style syscall that
would be usable for non-directory descriptors (with empty relative
pathname). Introduce new flag (AT_EMPTY_PATH) to deal with that and
corresponding LOOKUP_EMPTY; teach user_path_at() and path_init() to
deal with the latter.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 29 |
1 files changed, 19 insertions, 10 deletions
diff --git a/fs/namei.c b/fs/namei.c index abc8d2df121c..83e92bab79a6 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -136,7 +136,7 @@ static int do_getname(const char __user *filename, char *page) | |||
136 | return retval; | 136 | return retval; |
137 | } | 137 | } |
138 | 138 | ||
139 | char * getname(const char __user * filename) | 139 | static char *getname_flags(const char __user * filename, int flags) |
140 | { | 140 | { |
141 | char *tmp, *result; | 141 | char *tmp, *result; |
142 | 142 | ||
@@ -147,14 +147,21 @@ char * getname(const char __user * filename) | |||
147 | 147 | ||
148 | result = tmp; | 148 | result = tmp; |
149 | if (retval < 0) { | 149 | if (retval < 0) { |
150 | __putname(tmp); | 150 | if (retval != -ENOENT || !(flags & LOOKUP_EMPTY)) { |
151 | result = ERR_PTR(retval); | 151 | __putname(tmp); |
152 | result = ERR_PTR(retval); | ||
153 | } | ||
152 | } | 154 | } |
153 | } | 155 | } |
154 | audit_getname(result); | 156 | audit_getname(result); |
155 | return result; | 157 | return result; |
156 | } | 158 | } |
157 | 159 | ||
160 | char *getname(const char __user * filename) | ||
161 | { | ||
162 | return getname_flags(filename, 0); | ||
163 | } | ||
164 | |||
158 | #ifdef CONFIG_AUDITSYSCALL | 165 | #ifdef CONFIG_AUDITSYSCALL |
159 | void putname(const char *name) | 166 | void putname(const char *name) |
160 | { | 167 | { |
@@ -1544,13 +1551,15 @@ static int path_init(int dfd, const char *name, unsigned int flags, | |||
1544 | 1551 | ||
1545 | dentry = file->f_path.dentry; | 1552 | dentry = file->f_path.dentry; |
1546 | 1553 | ||
1547 | retval = -ENOTDIR; | 1554 | if (*name) { |
1548 | if (!S_ISDIR(dentry->d_inode->i_mode)) | 1555 | retval = -ENOTDIR; |
1549 | goto fput_fail; | 1556 | if (!S_ISDIR(dentry->d_inode->i_mode)) |
1557 | goto fput_fail; | ||
1550 | 1558 | ||
1551 | retval = file_permission(file, MAY_EXEC); | 1559 | retval = file_permission(file, MAY_EXEC); |
1552 | if (retval) | 1560 | if (retval) |
1553 | goto fput_fail; | 1561 | goto fput_fail; |
1562 | } | ||
1554 | 1563 | ||
1555 | nd->path = file->f_path; | 1564 | nd->path = file->f_path; |
1556 | if (flags & LOOKUP_RCU) { | 1565 | if (flags & LOOKUP_RCU) { |
@@ -1759,7 +1768,7 @@ int user_path_at(int dfd, const char __user *name, unsigned flags, | |||
1759 | struct path *path) | 1768 | struct path *path) |
1760 | { | 1769 | { |
1761 | struct nameidata nd; | 1770 | struct nameidata nd; |
1762 | char *tmp = getname(name); | 1771 | char *tmp = getname_flags(name, flags); |
1763 | int err = PTR_ERR(tmp); | 1772 | int err = PTR_ERR(tmp); |
1764 | if (!IS_ERR(tmp)) { | 1773 | if (!IS_ERR(tmp)) { |
1765 | 1774 | ||