Skip to content

Commit 119009d

Browse files
committed
Merge tag 'vfs-6.15-rc3.fixes.2' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull vfs fixes from Christian Brauner: - Revert the hfs{plus} deprecation warning that's also included in this pull request. The commit introducing the deprecation warning resides rather early in this branch. So simply dropping it would've rebased all other commits which I decided to avoid. Hence the revert in the same branch [ Background - the deprecation warning discussion resulted in people stepping up, and so hfs{plus} will have a maintainer taking care of it after all.. - Linus ] - Switch CONFIG_SYSFS_SYCALL default to n and decouple from CONFIG_EXPERT - Fix an audit bug caused by changes to our kernel path lookup helpers this cycle. Audit needs the parent path even if the dentry it tried to look up is negative - Ensure that the kernel path lookup helpers leave the passed in path argument clean when they return an error. This is consistent with all our other helpers - Ensure that vfs_getattr_nosec() calls bdev_statx() so the relevant information is available to kernel consumers as well - Don't set a timer and call schedule() if the timer will expire immediately in epoll - Make netfs lookup tables with __nonstring * tag 'vfs-6.15-rc3.fixes.2' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: Revert "hfs{plus}: add deprecation warning" fs: move the bdex_statx call to vfs_getattr_nosec netfs: Mark __nonstring lookup tables eventpoll: Set epoll timeout if it's in the future fs: ensure that *path_locked*() helpers leave passed path pristine fs: add kern_path_locked_negative() hfs{plus}: add deprecation warning Kconfig: switch CONFIG_SYSFS_SYCALL default to n
2 parents 6fe8131 + 408e450 commit 119009d

File tree

10 files changed

+112
-61
lines changed

10 files changed

+112
-61
lines changed

block/bdev.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1272,8 +1272,7 @@ void sync_bdevs(bool wait)
12721272
/*
12731273
* Handle STATX_{DIOALIGN, WRITE_ATOMIC} for block devices.
12741274
*/
1275-
void bdev_statx(struct path *path, struct kstat *stat,
1276-
u32 request_mask)
1275+
void bdev_statx(const struct path *path, struct kstat *stat, u32 request_mask)
12771276
{
12781277
struct inode *backing_inode;
12791278
struct block_device *bdev;

fs/eventpoll.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1996,6 +1996,14 @@ static int ep_try_send_events(struct eventpoll *ep,
19961996
return res;
19971997
}
19981998

1999+
static int ep_schedule_timeout(ktime_t *to)
2000+
{
2001+
if (to)
2002+
return ktime_after(*to, ktime_get());
2003+
else
2004+
return 1;
2005+
}
2006+
19992007
/**
20002008
* ep_poll - Retrieves ready events, and delivers them to the caller-supplied
20012009
* event buffer.
@@ -2103,7 +2111,7 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
21032111

21042112
write_unlock_irq(&ep->lock);
21052113

2106-
if (!eavail)
2114+
if (!eavail && ep_schedule_timeout(to))
21072115
timed_out = !schedule_hrtimeout_range(to, slack,
21082116
HRTIMER_MODE_ABS);
21092117
__set_current_state(TASK_RUNNING);

fs/namei.c

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1665,27 +1665,20 @@ static struct dentry *lookup_dcache(const struct qstr *name,
16651665
return dentry;
16661666
}
16671667

1668-
/*
1669-
* Parent directory has inode locked exclusive. This is one
1670-
* and only case when ->lookup() gets called on non in-lookup
1671-
* dentries - as the matter of fact, this only gets called
1672-
* when directory is guaranteed to have no in-lookup children
1673-
* at all.
1674-
* Will return -ENOENT if name isn't found and LOOKUP_CREATE wasn't passed.
1675-
* Will return -EEXIST if name is found and LOOKUP_EXCL was passed.
1676-
*/
1677-
struct dentry *lookup_one_qstr_excl(const struct qstr *name,
1678-
struct dentry *base,
1679-
unsigned int flags)
1668+
static struct dentry *lookup_one_qstr_excl_raw(const struct qstr *name,
1669+
struct dentry *base,
1670+
unsigned int flags)
16801671
{
1681-
struct dentry *dentry = lookup_dcache(name, base, flags);
1672+
struct dentry *dentry;
16821673
struct dentry *old;
1683-
struct inode *dir = base->d_inode;
1674+
struct inode *dir;
16841675

1676+
dentry = lookup_dcache(name, base, flags);
16851677
if (dentry)
1686-
goto found;
1678+
return dentry;
16871679

16881680
/* Don't create child dentry for a dead directory. */
1681+
dir = base->d_inode;
16891682
if (unlikely(IS_DEADDIR(dir)))
16901683
return ERR_PTR(-ENOENT);
16911684

@@ -1698,7 +1691,24 @@ struct dentry *lookup_one_qstr_excl(const struct qstr *name,
16981691
dput(dentry);
16991692
dentry = old;
17001693
}
1701-
found:
1694+
return dentry;
1695+
}
1696+
1697+
/*
1698+
* Parent directory has inode locked exclusive. This is one
1699+
* and only case when ->lookup() gets called on non in-lookup
1700+
* dentries - as the matter of fact, this only gets called
1701+
* when directory is guaranteed to have no in-lookup children
1702+
* at all.
1703+
* Will return -ENOENT if name isn't found and LOOKUP_CREATE wasn't passed.
1704+
* Will return -EEXIST if name is found and LOOKUP_EXCL was passed.
1705+
*/
1706+
struct dentry *lookup_one_qstr_excl(const struct qstr *name,
1707+
struct dentry *base, unsigned int flags)
1708+
{
1709+
struct dentry *dentry;
1710+
1711+
dentry = lookup_one_qstr_excl_raw(name, base, flags);
17021712
if (IS_ERR(dentry))
17031713
return dentry;
17041714
if (d_is_negative(dentry) && !(flags & LOOKUP_CREATE)) {
@@ -2742,23 +2752,48 @@ static int filename_parentat(int dfd, struct filename *name,
27422752
/* does lookup, returns the object with parent locked */
27432753
static struct dentry *__kern_path_locked(int dfd, struct filename *name, struct path *path)
27442754
{
2755+
struct path parent_path __free(path_put) = {};
27452756
struct dentry *d;
27462757
struct qstr last;
27472758
int type, error;
27482759

2749-
error = filename_parentat(dfd, name, 0, path, &last, &type);
2760+
error = filename_parentat(dfd, name, 0, &parent_path, &last, &type);
27502761
if (error)
27512762
return ERR_PTR(error);
2752-
if (unlikely(type != LAST_NORM)) {
2753-
path_put(path);
2763+
if (unlikely(type != LAST_NORM))
27542764
return ERR_PTR(-EINVAL);
2765+
inode_lock_nested(parent_path.dentry->d_inode, I_MUTEX_PARENT);
2766+
d = lookup_one_qstr_excl(&last, parent_path.dentry, 0);
2767+
if (IS_ERR(d)) {
2768+
inode_unlock(parent_path.dentry->d_inode);
2769+
return d;
27552770
}
2756-
inode_lock_nested(path->dentry->d_inode, I_MUTEX_PARENT);
2757-
d = lookup_one_qstr_excl(&last, path->dentry, 0);
2771+
path->dentry = no_free_ptr(parent_path.dentry);
2772+
path->mnt = no_free_ptr(parent_path.mnt);
2773+
return d;
2774+
}
2775+
2776+
struct dentry *kern_path_locked_negative(const char *name, struct path *path)
2777+
{
2778+
struct path parent_path __free(path_put) = {};
2779+
struct filename *filename __free(putname) = getname_kernel(name);
2780+
struct dentry *d;
2781+
struct qstr last;
2782+
int type, error;
2783+
2784+
error = filename_parentat(AT_FDCWD, filename, 0, &parent_path, &last, &type);
2785+
if (error)
2786+
return ERR_PTR(error);
2787+
if (unlikely(type != LAST_NORM))
2788+
return ERR_PTR(-EINVAL);
2789+
inode_lock_nested(parent_path.dentry->d_inode, I_MUTEX_PARENT);
2790+
d = lookup_one_qstr_excl_raw(&last, parent_path.dentry, 0);
27582791
if (IS_ERR(d)) {
2759-
inode_unlock(path->dentry->d_inode);
2760-
path_put(path);
2792+
inode_unlock(parent_path.dentry->d_inode);
2793+
return d;
27612794
}
2795+
path->dentry = no_free_ptr(parent_path.dentry);
2796+
path->mnt = no_free_ptr(parent_path.mnt);
27622797
return d;
27632798
}
27642799

fs/netfs/fscache_cache.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ void fscache_withdraw_cache(struct fscache_cache *cache)
372372
EXPORT_SYMBOL(fscache_withdraw_cache);
373373

374374
#ifdef CONFIG_PROC_FS
375-
static const char fscache_cache_states[NR__FSCACHE_CACHE_STATE] = "-PAEW";
375+
static const char fscache_cache_states[NR__FSCACHE_CACHE_STATE] __nonstring = "-PAEW";
376376

377377
/*
378378
* Generate a list of caches in /proc/fs/fscache/caches

fs/netfs/fscache_cookie.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ static LIST_HEAD(fscache_cookie_lru);
2929
static DEFINE_SPINLOCK(fscache_cookie_lru_lock);
3030
DEFINE_TIMER(fscache_cookie_lru_timer, fscache_cookie_lru_timed_out);
3131
static DECLARE_WORK(fscache_cookie_lru_work, fscache_cookie_lru_worker);
32-
static const char fscache_cookie_states[FSCACHE_COOKIE_STATE__NR] = "-LCAIFUWRD";
32+
static const char fscache_cookie_states[FSCACHE_COOKIE_STATE__NR] __nonstring = "-LCAIFUWRD";
3333
static unsigned int fscache_lru_cookie_timeout = 10 * HZ;
3434

3535
void fscache_print_cookie(struct fscache_cookie *cookie, char prefix)

fs/stat.c

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -204,12 +204,25 @@ int vfs_getattr_nosec(const struct path *path, struct kstat *stat,
204204
STATX_ATTR_DAX);
205205

206206
idmap = mnt_idmap(path->mnt);
207-
if (inode->i_op->getattr)
208-
return inode->i_op->getattr(idmap, path, stat,
209-
request_mask,
210-
query_flags);
207+
if (inode->i_op->getattr) {
208+
int ret;
209+
210+
ret = inode->i_op->getattr(idmap, path, stat, request_mask,
211+
query_flags);
212+
if (ret)
213+
return ret;
214+
} else {
215+
generic_fillattr(idmap, request_mask, inode, stat);
216+
}
217+
218+
/*
219+
* If this is a block device inode, override the filesystem attributes
220+
* with the block device specific parameters that need to be obtained
221+
* from the bdev backing inode.
222+
*/
223+
if (S_ISBLK(stat->mode))
224+
bdev_statx(path, stat, request_mask);
211225

212-
generic_fillattr(idmap, request_mask, inode, stat);
213226
return 0;
214227
}
215228
EXPORT_SYMBOL(vfs_getattr_nosec);
@@ -295,15 +308,6 @@ static int vfs_statx_path(struct path *path, int flags, struct kstat *stat,
295308
if (path_mounted(path))
296309
stat->attributes |= STATX_ATTR_MOUNT_ROOT;
297310
stat->attributes_mask |= STATX_ATTR_MOUNT_ROOT;
298-
299-
/*
300-
* If this is a block device inode, override the filesystem
301-
* attributes with the block device specific parameters that need to be
302-
* obtained from the bdev backing inode.
303-
*/
304-
if (S_ISBLK(stat->mode))
305-
bdev_statx(path, stat, request_mask);
306-
307311
return 0;
308312
}
309313

include/linux/blkdev.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1685,7 +1685,7 @@ int sync_blockdev(struct block_device *bdev);
16851685
int sync_blockdev_range(struct block_device *bdev, loff_t lstart, loff_t lend);
16861686
int sync_blockdev_nowait(struct block_device *bdev);
16871687
void sync_bdevs(bool wait);
1688-
void bdev_statx(struct path *, struct kstat *, u32);
1688+
void bdev_statx(const struct path *path, struct kstat *stat, u32 request_mask);
16891689
void printk_all_partitions(void);
16901690
int __init early_lookup_bdev(const char *pathname, dev_t *dev);
16911691
#else
@@ -1703,8 +1703,8 @@ static inline int sync_blockdev_nowait(struct block_device *bdev)
17031703
static inline void sync_bdevs(bool wait)
17041704
{
17051705
}
1706-
static inline void bdev_statx(struct path *path, struct kstat *stat,
1707-
u32 request_mask)
1706+
static inline void bdev_statx(const struct path *path, struct kstat *stat,
1707+
u32 request_mask)
17081708
{
17091709
}
17101710
static inline void printk_all_partitions(void)

include/linux/namei.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ extern struct dentry *kern_path_create(int, const char *, struct path *, unsigne
6262
extern struct dentry *user_path_create(int, const char __user *, struct path *, unsigned int);
6363
extern void done_path_create(struct path *, struct dentry *);
6464
extern struct dentry *kern_path_locked(const char *, struct path *);
65+
extern struct dentry *kern_path_locked_negative(const char *, struct path *);
6566
extern struct dentry *user_path_locked_at(int , const char __user *, struct path *);
6667
int vfs_path_parent_lookup(struct filename *filename, unsigned int flags,
6768
struct path *parent, struct qstr *last, int *type,

init/Kconfig

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1555,6 +1555,16 @@ config SYSCTL_ARCH_UNALIGN_ALLOW
15551555
the unaligned access emulation.
15561556
see arch/parisc/kernel/unaligned.c for reference
15571557

1558+
config SYSFS_SYSCALL
1559+
bool "Sysfs syscall support"
1560+
default n
1561+
help
1562+
sys_sysfs is an obsolete system call no longer supported in libc.
1563+
Note that disabling this option is more secure but might break
1564+
compatibility with some systems.
1565+
1566+
If unsure say N here.
1567+
15581568
config HAVE_PCSPKR_PLATFORM
15591569
bool
15601570

@@ -1599,16 +1609,6 @@ config SGETMASK_SYSCALL
15991609

16001610
If unsure, leave the default option here.
16011611

1602-
config SYSFS_SYSCALL
1603-
bool "Sysfs syscall support" if EXPERT
1604-
default y
1605-
help
1606-
sys_sysfs is an obsolete system call no longer supported in libc.
1607-
Note that disabling this option is more secure but might break
1608-
compatibility with some systems.
1609-
1610-
If unsure say Y here.
1611-
16121612
config FHANDLE
16131613
bool "open by fhandle syscalls" if EXPERT
16141614
select EXPORTFS

kernel/audit_watch.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -347,12 +347,17 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
347347
/* Get path information necessary for adding watches. */
348348
static int audit_get_nd(struct audit_watch *watch, struct path *parent)
349349
{
350-
struct dentry *d = kern_path_locked(watch->path, parent);
350+
struct dentry *d;
351+
352+
d = kern_path_locked_negative(watch->path, parent);
351353
if (IS_ERR(d))
352354
return PTR_ERR(d);
353-
/* update watch filter fields */
354-
watch->dev = d->d_sb->s_dev;
355-
watch->ino = d_backing_inode(d)->i_ino;
355+
356+
if (d_is_positive(d)) {
357+
/* update watch filter fields */
358+
watch->dev = d->d_sb->s_dev;
359+
watch->ino = d_backing_inode(d)->i_ino;
360+
}
356361

357362
inode_unlock(d_backing_inode(parent->dentry));
358363
dput(d);
@@ -418,11 +423,10 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list)
418423
/* caller expects mutex locked */
419424
mutex_lock(&audit_filter_mutex);
420425

421-
if (ret && ret != -ENOENT) {
426+
if (ret) {
422427
audit_put_watch(watch);
423428
return ret;
424429
}
425-
ret = 0;
426430

427431
/* either find an old parent or attach a new one */
428432
parent = audit_find_parent(d_backing_inode(parent_path.dentry));

0 commit comments

Comments
 (0)