Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

getname_maybe_null() - the third variant of pathname copy-in

Semantics used by statx(2) (and later *xattrat(2)): without AT_EMPTY_PATH
it's standard getname() (i.e. ERR_PTR(-ENOENT) on empty string,
ERR_PTR(-EFAULT) on NULL), with AT_EMPTY_PATH both empty string and
NULL are accepted.

Calling conventions: getname_maybe_null(user_pointer, flags) returns
* pointer to struct filename when non-empty string had been
successfully read
* ERR_PTR(...) on error
* NULL if an empty string or NULL pointer had been given
with AT_EMPTY_PATH in the flags argument.

It tries to avoid allocation in the last case; it's not always
able to do so, in which case the temporary struct filename instance
is freed and NULL returned anyway.

Fast path is inlined.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Al Viro e896474f 5b313bcb

+37 -31
+23 -7
fs/namei.c
··· 211 211 return result; 212 212 } 213 213 214 - struct filename * 215 - getname_uflags(const char __user *filename, int uflags) 214 + struct filename *getname_uflags(const char __user *filename, int uflags) 216 215 { 217 216 int flags = (uflags & AT_EMPTY_PATH) ? LOOKUP_EMPTY : 0; 218 217 219 218 return getname_flags(filename, flags); 220 219 } 221 220 222 - struct filename * 223 - getname(const char __user * filename) 221 + struct filename *getname(const char __user * filename) 224 222 { 225 223 return getname_flags(filename, 0); 226 224 } 227 225 228 - struct filename * 229 - getname_kernel(const char * filename) 226 + struct filename *__getname_maybe_null(const char __user *pathname) 227 + { 228 + struct filename *name; 229 + char c; 230 + 231 + /* try to save on allocations; loss on um, though */ 232 + if (get_user(c, pathname)) 233 + return ERR_PTR(-EFAULT); 234 + if (!c) 235 + return NULL; 236 + 237 + name = getname_flags(pathname, LOOKUP_EMPTY); 238 + if (!IS_ERR(name) && !(name->name[0])) { 239 + putname(name); 240 + name = NULL; 241 + } 242 + return name; 243 + } 244 + 245 + struct filename *getname_kernel(const char * filename) 230 246 { 231 247 struct filename *result; 232 248 int len = strlen(filename) + 1; ··· 280 264 281 265 void putname(struct filename *name) 282 266 { 283 - if (IS_ERR(name)) 267 + if (IS_ERR_OR_NULL(name)) 284 268 return; 285 269 286 270 if (WARN_ON_ONCE(!atomic_read(&name->refcnt)))
+4 -24
fs/stat.c
··· 326 326 { 327 327 int ret; 328 328 int statx_flags = flags | AT_NO_AUTOMOUNT; 329 - struct filename *name; 329 + struct filename *name = getname_maybe_null(filename, flags); 330 330 331 - /* 332 - * Work around glibc turning fstat() into fstatat(AT_EMPTY_PATH) 333 - * 334 - * If AT_EMPTY_PATH is set, we expect the common case to be that 335 - * empty path, and avoid doing all the extra pathname work. 336 - */ 337 - if (flags == AT_EMPTY_PATH && vfs_empty_path(dfd, filename)) 331 + if (!name && dfd >= 0) 338 332 return vfs_fstat(dfd, stat); 339 333 340 - name = getname_flags(filename, getname_statx_lookup_flags(statx_flags)); 341 334 ret = vfs_statx(dfd, name, statx_flags, stat, STATX_BASIC_STATS); 342 335 putname(name); 343 336 ··· 767 774 struct statx __user *, buffer) 768 775 { 769 776 int ret; 770 - unsigned lflags; 771 - struct filename *name; 777 + struct filename *name = getname_maybe_null(filename, flags); 772 778 773 - /* 774 - * Short-circuit handling of NULL and "" paths. 775 - * 776 - * For a NULL path we require and accept only the AT_EMPTY_PATH flag 777 - * (possibly |'d with AT_STATX flags). 778 - * 779 - * However, glibc on 32-bit architectures implements fstatat as statx 780 - * with the "" pathname and AT_NO_AUTOMOUNT | AT_EMPTY_PATH flags. 781 - * Supporting this results in the uglification below. 782 - */ 783 - lflags = flags & ~(AT_NO_AUTOMOUNT | AT_STATX_SYNC_TYPE); 784 - if (lflags == AT_EMPTY_PATH && vfs_empty_path(dfd, filename)) 779 + if (!name && dfd >= 0) 785 780 return do_statx_fd(dfd, flags & ~AT_NO_AUTOMOUNT, mask, buffer); 786 781 787 - name = getname_flags(filename, getname_statx_lookup_flags(flags)); 788 782 ret = do_statx(dfd, name, flags, mask, buffer); 789 783 putname(name); 790 784
+10
include/linux/fs.h
··· 2766 2766 extern struct filename *getname_uflags(const char __user *, int); 2767 2767 extern struct filename *getname(const char __user *); 2768 2768 extern struct filename *getname_kernel(const char *); 2769 + extern struct filename *__getname_maybe_null(const char __user *); 2770 + static inline struct filename *getname_maybe_null(const char __user *name, int flags) 2771 + { 2772 + if (!(flags & AT_EMPTY_PATH)) 2773 + return getname(name); 2774 + 2775 + if (!name) 2776 + return NULL; 2777 + return __getname_maybe_null(name); 2778 + } 2769 2779 extern void putname(struct filename *name); 2770 2780 2771 2781 extern int finish_open(struct file *file, struct dentry *dentry,