Commit f52e0c11305aa09ed56cad97ffc8f0cdc3d78b5d
1 parent
5fe0c23788
Exists in
master
and in
20 other branches
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>
Showing 3 changed files with 21 additions and 10 deletions Side-by-side Diff
fs/namei.c
... | ... | @@ -136,7 +136,7 @@ |
136 | 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 | 141 | char *tmp, *result; |
142 | 142 | |
143 | 143 | |
... | ... | @@ -147,14 +147,21 @@ |
147 | 147 | |
148 | 148 | result = tmp; |
149 | 149 | if (retval < 0) { |
150 | - __putname(tmp); | |
151 | - result = ERR_PTR(retval); | |
150 | + if (retval != -ENOENT || !(flags & LOOKUP_EMPTY)) { | |
151 | + __putname(tmp); | |
152 | + result = ERR_PTR(retval); | |
153 | + } | |
152 | 154 | } |
153 | 155 | } |
154 | 156 | audit_getname(result); |
155 | 157 | return result; |
156 | 158 | } |
157 | 159 | |
160 | +char *getname(const char __user * filename) | |
161 | +{ | |
162 | + return getname_flags(filename, 0); | |
163 | +} | |
164 | + | |
158 | 165 | #ifdef CONFIG_AUDITSYSCALL |
159 | 166 | void putname(const char *name) |
160 | 167 | { |
161 | 168 | |
... | ... | @@ -1544,13 +1551,15 @@ |
1544 | 1551 | |
1545 | 1552 | dentry = file->f_path.dentry; |
1546 | 1553 | |
1547 | - retval = -ENOTDIR; | |
1548 | - if (!S_ISDIR(dentry->d_inode->i_mode)) | |
1549 | - goto fput_fail; | |
1554 | + if (*name) { | |
1555 | + retval = -ENOTDIR; | |
1556 | + if (!S_ISDIR(dentry->d_inode->i_mode)) | |
1557 | + goto fput_fail; | |
1550 | 1558 | |
1551 | - retval = file_permission(file, MAY_EXEC); | |
1552 | - if (retval) | |
1553 | - goto fput_fail; | |
1559 | + retval = file_permission(file, MAY_EXEC); | |
1560 | + if (retval) | |
1561 | + goto fput_fail; | |
1562 | + } | |
1554 | 1563 | |
1555 | 1564 | nd->path = file->f_path; |
1556 | 1565 | if (flags & LOOKUP_RCU) { |
... | ... | @@ -1759,7 +1768,7 @@ |
1759 | 1768 | struct path *path) |
1760 | 1769 | { |
1761 | 1770 | struct nameidata nd; |
1762 | - char *tmp = getname(name); | |
1771 | + char *tmp = getname_flags(name, flags); | |
1763 | 1772 | int err = PTR_ERR(tmp); |
1764 | 1773 | if (!IS_ERR(tmp)) { |
1765 | 1774 |
include/linux/fcntl.h
... | ... | @@ -46,6 +46,7 @@ |
46 | 46 | unlinking file. */ |
47 | 47 | #define AT_SYMLINK_FOLLOW 0x400 /* Follow symbolic links. */ |
48 | 48 | #define AT_NO_AUTOMOUNT 0x800 /* Suppress terminal automount traversal */ |
49 | +#define AT_EMPTY_PATH 0x1000 /* Allow empty relative pathname */ | |
49 | 50 | |
50 | 51 | #ifdef __KERNEL__ |
51 | 52 |