diff options
| author | Steven Rostedt <rostedt@goodmis.org> | 2026-09-02 09:55:01 -0400 |
|---|---|---|
| committer | Steven Rostedt <rostedt@goodmis.org> | 2026-09-02 11:08:21 -0400 |
| commit | 4617721c502b2ddaa4e324e86da4997edf738fa5 (patch) | |
| tree | 350aa83b47da0b574a814795392b20b0bed83cbc /fs/jfs/acl.c | |
| download | linux-stable-4617721c502b2ddaa4e324e86da4997edf738fa5.tar.gz linux-stable-4617721c502b2ddaa4e324e86da4997edf738fa5.zip | |
ftrace: Synchronize the initialization of ftrace_opsgrafted
There's some internal state that ftrace_ops needs to have set, but since
it can be declared outside of the ftrace.c code, it calls
ftrace_ops_init() on the ops in every global function. The issue is that
if two tasks call it on the same ops at the same time it is possible to
have the initialization of one corrupt the initialization of the other
call.
Create a ops_mutex to use to synchronize every initialization of the
ftrace_ops. The mutex is taken within checking the ftrace_ops flag that
states it was initializied but the flag is checked again after the mutex
has been taken. Checking first outside the mutex allows it to shortcut
having to take the mutex. But then the check needs to be done again after
the mute is taken in case of races.
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260902095501.6b59af20@gandalf.local.home
Fixes: f04f24fb7e48d ("ftrace, kprobes: Fix a deadlock on ftrace_regex_lock")
Reported-by: sashiko-bot@kernel.org
Close: https://lore.kernel.org/all/20260829025528.49A831F000E9@smtp.kernel.org/
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'fs/jfs/acl.c')
| -rw-r--r-- | fs/jfs/acl.c | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c new file mode 100644 index 000000000..16b71a23f --- /dev/null +++ b/fs/jfs/acl.c @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) International Business Machines Corp., 2002-2004 + * Copyright (C) Andreas Gruenbacher, 2001 + * Copyright (C) Linus Torvalds, 1991, 1992 + */ + +#include <linux/sched.h> +#include <linux/slab.h> +#include <linux/fs.h> +#include <linux/posix_acl_xattr.h> +#include "jfs_incore.h" +#include "jfs_txnmgr.h" +#include "jfs_xattr.h" +#include "jfs_acl.h" + +struct posix_acl *jfs_get_acl(struct inode *inode, int type, bool rcu) +{ + struct posix_acl *acl; + char *ea_name; + int size; + char *value = NULL; + + if (rcu) + return ERR_PTR(-ECHILD); + + switch(type) { + case ACL_TYPE_ACCESS: + ea_name = XATTR_NAME_POSIX_ACL_ACCESS; + break; + case ACL_TYPE_DEFAULT: + ea_name = XATTR_NAME_POSIX_ACL_DEFAULT; + break; + default: + return ERR_PTR(-EINVAL); + } + + size = __jfs_getxattr(inode, ea_name, NULL, 0); + + if (size > 0) { + value = kmalloc(size, GFP_KERNEL); + if (!value) + return ERR_PTR(-ENOMEM); + size = __jfs_getxattr(inode, ea_name, value, size); + } + + if (size < 0) { + if (size == -ENODATA) + acl = NULL; + else + acl = ERR_PTR(size); + } else { + acl = posix_acl_from_xattr(&init_user_ns, value, size); + } + kfree(value); + return acl; +} + +static int __jfs_set_acl(tid_t tid, struct inode *inode, int type, + struct posix_acl *acl) +{ + char *ea_name; + int rc; + size_t size = 0; + char *value = NULL; + + switch (type) { + case ACL_TYPE_ACCESS: + ea_name = XATTR_NAME_POSIX_ACL_ACCESS; + break; + case ACL_TYPE_DEFAULT: + ea_name = XATTR_NAME_POSIX_ACL_DEFAULT; + break; + default: + return -EINVAL; + } + + if (acl) { + value = posix_acl_to_xattr(&init_user_ns, acl, &size, GFP_KERNEL); + if (!value) + return -ENOMEM; + } + rc = __jfs_setxattr(tid, inode, ea_name, value, size, 0); + kfree(value); + + if (!rc) + set_cached_acl(inode, type, acl); + + return rc; +} + +int jfs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, + struct posix_acl *acl, int type) +{ + int rc; + tid_t tid; + int update_mode = 0; + struct inode *inode = d_inode(dentry); + umode_t mode = inode->i_mode; + + tid = txBegin(inode->i_sb, 0); + mutex_lock(&JFS_IP(inode)->commit_mutex); + if (type == ACL_TYPE_ACCESS && acl) { + rc = posix_acl_update_mode(&nop_mnt_idmap, inode, &mode, &acl); + if (rc) + goto end_tx; + if (mode != inode->i_mode) + update_mode = 1; + } + rc = __jfs_set_acl(tid, inode, type, acl); + if (!rc) { + if (update_mode) { + inode->i_mode = mode; + inode_set_ctime_current(inode); + mark_inode_dirty(inode); + } + rc = txCommit(tid, 1, &inode, 0); + } +end_tx: + txEnd(tid); + mutex_unlock(&JFS_IP(inode)->commit_mutex); + return rc; +} + +int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir) +{ + struct posix_acl *default_acl, *acl; + int rc = 0; + + rc = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl); + if (rc) + return rc; + + if (default_acl) { + rc = __jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, default_acl); + posix_acl_release(default_acl); + } else { + inode->i_default_acl = NULL; + } + + if (acl) { + if (!rc) + rc = __jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, acl); + posix_acl_release(acl); + } else { + inode->i_acl = NULL; + } + + JFS_IP(inode)->mode2 = (JFS_IP(inode)->mode2 & 0xffff0000) | + inode->i_mode; + + return rc; +} |
