Commit f52e0c11305aa09ed56cad97ffc8f0cdc3d78b5d

Authored by Al Viro
1 parent 5fe0c23788

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

... ... @@ -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  
include/linux/namei.h
... ... @@ -64,6 +64,7 @@
64 64  
65 65 #define LOOKUP_JUMPED 0x1000
66 66 #define LOOKUP_ROOT 0x2000
  67 +#define LOOKUP_EMPTY 0x4000
67 68  
68 69 extern int user_path_at(int, const char __user *, unsigned, struct path *);
69 70