mirror of
https://github.com/torvalds/linux.git
synced 2025-12-01 07:26:02 +07:00
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
This commit is contained in:
@@ -1272,8 +1272,7 @@ void sync_bdevs(bool wait)
|
||||
/*
|
||||
* Handle STATX_{DIOALIGN, WRITE_ATOMIC} for block devices.
|
||||
*/
|
||||
void bdev_statx(struct path *path, struct kstat *stat,
|
||||
u32 request_mask)
|
||||
void bdev_statx(const struct path *path, struct kstat *stat, u32 request_mask)
|
||||
{
|
||||
struct inode *backing_inode;
|
||||
struct block_device *bdev;
|
||||
|
||||
@@ -1996,6 +1996,14 @@ static int ep_try_send_events(struct eventpoll *ep,
|
||||
return res;
|
||||
}
|
||||
|
||||
static int ep_schedule_timeout(ktime_t *to)
|
||||
{
|
||||
if (to)
|
||||
return ktime_after(*to, ktime_get());
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* ep_poll - Retrieves ready events, and delivers them to the caller-supplied
|
||||
* event buffer.
|
||||
@@ -2103,7 +2111,7 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
|
||||
|
||||
write_unlock_irq(&ep->lock);
|
||||
|
||||
if (!eavail)
|
||||
if (!eavail && ep_schedule_timeout(to))
|
||||
timed_out = !schedule_hrtimeout_range(to, slack,
|
||||
HRTIMER_MODE_ABS);
|
||||
__set_current_state(TASK_RUNNING);
|
||||
|
||||
83
fs/namei.c
83
fs/namei.c
@@ -1665,27 +1665,20 @@ static struct dentry *lookup_dcache(const struct qstr *name,
|
||||
return dentry;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parent directory has inode locked exclusive. This is one
|
||||
* and only case when ->lookup() gets called on non in-lookup
|
||||
* dentries - as the matter of fact, this only gets called
|
||||
* when directory is guaranteed to have no in-lookup children
|
||||
* at all.
|
||||
* Will return -ENOENT if name isn't found and LOOKUP_CREATE wasn't passed.
|
||||
* Will return -EEXIST if name is found and LOOKUP_EXCL was passed.
|
||||
*/
|
||||
struct dentry *lookup_one_qstr_excl(const struct qstr *name,
|
||||
struct dentry *base,
|
||||
unsigned int flags)
|
||||
static struct dentry *lookup_one_qstr_excl_raw(const struct qstr *name,
|
||||
struct dentry *base,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct dentry *dentry = lookup_dcache(name, base, flags);
|
||||
struct dentry *dentry;
|
||||
struct dentry *old;
|
||||
struct inode *dir = base->d_inode;
|
||||
struct inode *dir;
|
||||
|
||||
dentry = lookup_dcache(name, base, flags);
|
||||
if (dentry)
|
||||
goto found;
|
||||
return dentry;
|
||||
|
||||
/* Don't create child dentry for a dead directory. */
|
||||
dir = base->d_inode;
|
||||
if (unlikely(IS_DEADDIR(dir)))
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
@@ -1698,7 +1691,24 @@ struct dentry *lookup_one_qstr_excl(const struct qstr *name,
|
||||
dput(dentry);
|
||||
dentry = old;
|
||||
}
|
||||
found:
|
||||
return dentry;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parent directory has inode locked exclusive. This is one
|
||||
* and only case when ->lookup() gets called on non in-lookup
|
||||
* dentries - as the matter of fact, this only gets called
|
||||
* when directory is guaranteed to have no in-lookup children
|
||||
* at all.
|
||||
* Will return -ENOENT if name isn't found and LOOKUP_CREATE wasn't passed.
|
||||
* Will return -EEXIST if name is found and LOOKUP_EXCL was passed.
|
||||
*/
|
||||
struct dentry *lookup_one_qstr_excl(const struct qstr *name,
|
||||
struct dentry *base, unsigned int flags)
|
||||
{
|
||||
struct dentry *dentry;
|
||||
|
||||
dentry = lookup_one_qstr_excl_raw(name, base, flags);
|
||||
if (IS_ERR(dentry))
|
||||
return dentry;
|
||||
if (d_is_negative(dentry) && !(flags & LOOKUP_CREATE)) {
|
||||
@@ -2742,23 +2752,48 @@ static int filename_parentat(int dfd, struct filename *name,
|
||||
/* does lookup, returns the object with parent locked */
|
||||
static struct dentry *__kern_path_locked(int dfd, struct filename *name, struct path *path)
|
||||
{
|
||||
struct path parent_path __free(path_put) = {};
|
||||
struct dentry *d;
|
||||
struct qstr last;
|
||||
int type, error;
|
||||
|
||||
error = filename_parentat(dfd, name, 0, path, &last, &type);
|
||||
error = filename_parentat(dfd, name, 0, &parent_path, &last, &type);
|
||||
if (error)
|
||||
return ERR_PTR(error);
|
||||
if (unlikely(type != LAST_NORM)) {
|
||||
path_put(path);
|
||||
if (unlikely(type != LAST_NORM))
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
inode_lock_nested(path->dentry->d_inode, I_MUTEX_PARENT);
|
||||
d = lookup_one_qstr_excl(&last, path->dentry, 0);
|
||||
inode_lock_nested(parent_path.dentry->d_inode, I_MUTEX_PARENT);
|
||||
d = lookup_one_qstr_excl(&last, parent_path.dentry, 0);
|
||||
if (IS_ERR(d)) {
|
||||
inode_unlock(path->dentry->d_inode);
|
||||
path_put(path);
|
||||
inode_unlock(parent_path.dentry->d_inode);
|
||||
return d;
|
||||
}
|
||||
path->dentry = no_free_ptr(parent_path.dentry);
|
||||
path->mnt = no_free_ptr(parent_path.mnt);
|
||||
return d;
|
||||
}
|
||||
|
||||
struct dentry *kern_path_locked_negative(const char *name, struct path *path)
|
||||
{
|
||||
struct path parent_path __free(path_put) = {};
|
||||
struct filename *filename __free(putname) = getname_kernel(name);
|
||||
struct dentry *d;
|
||||
struct qstr last;
|
||||
int type, error;
|
||||
|
||||
error = filename_parentat(AT_FDCWD, filename, 0, &parent_path, &last, &type);
|
||||
if (error)
|
||||
return ERR_PTR(error);
|
||||
if (unlikely(type != LAST_NORM))
|
||||
return ERR_PTR(-EINVAL);
|
||||
inode_lock_nested(parent_path.dentry->d_inode, I_MUTEX_PARENT);
|
||||
d = lookup_one_qstr_excl_raw(&last, parent_path.dentry, 0);
|
||||
if (IS_ERR(d)) {
|
||||
inode_unlock(parent_path.dentry->d_inode);
|
||||
return d;
|
||||
}
|
||||
path->dentry = no_free_ptr(parent_path.dentry);
|
||||
path->mnt = no_free_ptr(parent_path.mnt);
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
@@ -372,7 +372,7 @@ void fscache_withdraw_cache(struct fscache_cache *cache)
|
||||
EXPORT_SYMBOL(fscache_withdraw_cache);
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
static const char fscache_cache_states[NR__FSCACHE_CACHE_STATE] = "-PAEW";
|
||||
static const char fscache_cache_states[NR__FSCACHE_CACHE_STATE] __nonstring = "-PAEW";
|
||||
|
||||
/*
|
||||
* Generate a list of caches in /proc/fs/fscache/caches
|
||||
|
||||
@@ -29,7 +29,7 @@ static LIST_HEAD(fscache_cookie_lru);
|
||||
static DEFINE_SPINLOCK(fscache_cookie_lru_lock);
|
||||
DEFINE_TIMER(fscache_cookie_lru_timer, fscache_cookie_lru_timed_out);
|
||||
static DECLARE_WORK(fscache_cookie_lru_work, fscache_cookie_lru_worker);
|
||||
static const char fscache_cookie_states[FSCACHE_COOKIE_STATE__NR] = "-LCAIFUWRD";
|
||||
static const char fscache_cookie_states[FSCACHE_COOKIE_STATE__NR] __nonstring = "-LCAIFUWRD";
|
||||
static unsigned int fscache_lru_cookie_timeout = 10 * HZ;
|
||||
|
||||
void fscache_print_cookie(struct fscache_cookie *cookie, char prefix)
|
||||
|
||||
32
fs/stat.c
32
fs/stat.c
@@ -204,12 +204,25 @@ int vfs_getattr_nosec(const struct path *path, struct kstat *stat,
|
||||
STATX_ATTR_DAX);
|
||||
|
||||
idmap = mnt_idmap(path->mnt);
|
||||
if (inode->i_op->getattr)
|
||||
return inode->i_op->getattr(idmap, path, stat,
|
||||
request_mask,
|
||||
query_flags);
|
||||
if (inode->i_op->getattr) {
|
||||
int ret;
|
||||
|
||||
ret = inode->i_op->getattr(idmap, path, stat, request_mask,
|
||||
query_flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
generic_fillattr(idmap, request_mask, inode, stat);
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is a block device inode, override the filesystem attributes
|
||||
* with the block device specific parameters that need to be obtained
|
||||
* from the bdev backing inode.
|
||||
*/
|
||||
if (S_ISBLK(stat->mode))
|
||||
bdev_statx(path, stat, request_mask);
|
||||
|
||||
generic_fillattr(idmap, request_mask, inode, stat);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(vfs_getattr_nosec);
|
||||
@@ -295,15 +308,6 @@ static int vfs_statx_path(struct path *path, int flags, struct kstat *stat,
|
||||
if (path_mounted(path))
|
||||
stat->attributes |= STATX_ATTR_MOUNT_ROOT;
|
||||
stat->attributes_mask |= STATX_ATTR_MOUNT_ROOT;
|
||||
|
||||
/*
|
||||
* If this is a block device inode, override the filesystem
|
||||
* attributes with the block device specific parameters that need to be
|
||||
* obtained from the bdev backing inode.
|
||||
*/
|
||||
if (S_ISBLK(stat->mode))
|
||||
bdev_statx(path, stat, request_mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1685,7 +1685,7 @@ int sync_blockdev(struct block_device *bdev);
|
||||
int sync_blockdev_range(struct block_device *bdev, loff_t lstart, loff_t lend);
|
||||
int sync_blockdev_nowait(struct block_device *bdev);
|
||||
void sync_bdevs(bool wait);
|
||||
void bdev_statx(struct path *, struct kstat *, u32);
|
||||
void bdev_statx(const struct path *path, struct kstat *stat, u32 request_mask);
|
||||
void printk_all_partitions(void);
|
||||
int __init early_lookup_bdev(const char *pathname, dev_t *dev);
|
||||
#else
|
||||
@@ -1703,8 +1703,8 @@ static inline int sync_blockdev_nowait(struct block_device *bdev)
|
||||
static inline void sync_bdevs(bool wait)
|
||||
{
|
||||
}
|
||||
static inline void bdev_statx(struct path *path, struct kstat *stat,
|
||||
u32 request_mask)
|
||||
static inline void bdev_statx(const struct path *path, struct kstat *stat,
|
||||
u32 request_mask)
|
||||
{
|
||||
}
|
||||
static inline void printk_all_partitions(void)
|
||||
|
||||
@@ -62,6 +62,7 @@ extern struct dentry *kern_path_create(int, const char *, struct path *, unsigne
|
||||
extern struct dentry *user_path_create(int, const char __user *, struct path *, unsigned int);
|
||||
extern void done_path_create(struct path *, struct dentry *);
|
||||
extern struct dentry *kern_path_locked(const char *, struct path *);
|
||||
extern struct dentry *kern_path_locked_negative(const char *, struct path *);
|
||||
extern struct dentry *user_path_locked_at(int , const char __user *, struct path *);
|
||||
int vfs_path_parent_lookup(struct filename *filename, unsigned int flags,
|
||||
struct path *parent, struct qstr *last, int *type,
|
||||
|
||||
20
init/Kconfig
20
init/Kconfig
@@ -1555,6 +1555,16 @@ config SYSCTL_ARCH_UNALIGN_ALLOW
|
||||
the unaligned access emulation.
|
||||
see arch/parisc/kernel/unaligned.c for reference
|
||||
|
||||
config SYSFS_SYSCALL
|
||||
bool "Sysfs syscall support"
|
||||
default n
|
||||
help
|
||||
sys_sysfs is an obsolete system call no longer supported in libc.
|
||||
Note that disabling this option is more secure but might break
|
||||
compatibility with some systems.
|
||||
|
||||
If unsure say N here.
|
||||
|
||||
config HAVE_PCSPKR_PLATFORM
|
||||
bool
|
||||
|
||||
@@ -1599,16 +1609,6 @@ config SGETMASK_SYSCALL
|
||||
|
||||
If unsure, leave the default option here.
|
||||
|
||||
config SYSFS_SYSCALL
|
||||
bool "Sysfs syscall support" if EXPERT
|
||||
default y
|
||||
help
|
||||
sys_sysfs is an obsolete system call no longer supported in libc.
|
||||
Note that disabling this option is more secure but might break
|
||||
compatibility with some systems.
|
||||
|
||||
If unsure say Y here.
|
||||
|
||||
config FHANDLE
|
||||
bool "open by fhandle syscalls" if EXPERT
|
||||
select EXPORTFS
|
||||
|
||||
@@ -347,12 +347,17 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
|
||||
/* Get path information necessary for adding watches. */
|
||||
static int audit_get_nd(struct audit_watch *watch, struct path *parent)
|
||||
{
|
||||
struct dentry *d = kern_path_locked(watch->path, parent);
|
||||
struct dentry *d;
|
||||
|
||||
d = kern_path_locked_negative(watch->path, parent);
|
||||
if (IS_ERR(d))
|
||||
return PTR_ERR(d);
|
||||
/* update watch filter fields */
|
||||
watch->dev = d->d_sb->s_dev;
|
||||
watch->ino = d_backing_inode(d)->i_ino;
|
||||
|
||||
if (d_is_positive(d)) {
|
||||
/* update watch filter fields */
|
||||
watch->dev = d->d_sb->s_dev;
|
||||
watch->ino = d_backing_inode(d)->i_ino;
|
||||
}
|
||||
|
||||
inode_unlock(d_backing_inode(parent->dentry));
|
||||
dput(d);
|
||||
@@ -418,11 +423,10 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list)
|
||||
/* caller expects mutex locked */
|
||||
mutex_lock(&audit_filter_mutex);
|
||||
|
||||
if (ret && ret != -ENOENT) {
|
||||
if (ret) {
|
||||
audit_put_watch(watch);
|
||||
return ret;
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
/* either find an old parent or attach a new one */
|
||||
parent = audit_find_parent(d_backing_inode(parent_path.dentry));
|
||||
|
||||
Reference in New Issue
Block a user