mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 02:21:52 +09:00
Merge 16c54d6a49 ("mm: fix apply_to_existing_page_range()") into android14-6.1-lts
Steps on the way to 6.1.135 Change-Id: I789088e35ba0c1f8c14466c6440828e3249159df Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
3
Makefile
3
Makefile
@@ -1103,6 +1103,9 @@ KBUILD_CFLAGS += $(call cc-option,-Werror=incompatible-pointer-types)
|
||||
# Require designated initializers for all marked structures
|
||||
KBUILD_CFLAGS += $(call cc-option,-Werror=designated-init)
|
||||
|
||||
# Ensure compilers do not transform certain loops into calls to wcslen()
|
||||
KBUILD_CFLAGS += -fno-builtin-wcslen
|
||||
|
||||
# change __FILE__ to the relative path from the srctree
|
||||
KBUILD_CPPFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
|
||||
|
||||
|
||||
@@ -173,18 +173,6 @@ static __init int setup_node(int pxm)
|
||||
return acpi_map_pxm_to_node(pxm);
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback for SLIT parsing. pxm_to_node() returns NUMA_NO_NODE for
|
||||
* I/O localities since SRAT does not list them. I/O localities are
|
||||
* not supported at this point.
|
||||
*/
|
||||
unsigned int numa_distance_cnt;
|
||||
|
||||
static inline unsigned int get_numa_distances_cnt(struct acpi_table_slit *slit)
|
||||
{
|
||||
return slit->locality_count;
|
||||
}
|
||||
|
||||
void __init numa_set_distance(int from, int to, int distance)
|
||||
{
|
||||
if ((u8)distance != distance || (from == to && distance != LOCAL_DISTANCE)) {
|
||||
|
||||
@@ -142,8 +142,6 @@ static void build_prologue(struct jit_ctx *ctx)
|
||||
*/
|
||||
if (seen_tail_call(ctx) && seen_call(ctx))
|
||||
move_reg(ctx, TCC_SAVED, REG_TCC);
|
||||
else
|
||||
emit_insn(ctx, nop);
|
||||
|
||||
ctx->stack_size = stack_adjust;
|
||||
}
|
||||
|
||||
@@ -25,11 +25,6 @@ struct jit_data {
|
||||
struct jit_ctx ctx;
|
||||
};
|
||||
|
||||
static inline void emit_nop(union loongarch_instruction *insn)
|
||||
{
|
||||
insn->word = INSN_NOP;
|
||||
}
|
||||
|
||||
#define emit_insn(ctx, func, ...) \
|
||||
do { \
|
||||
if (ctx->image != NULL) { \
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/nospec.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_fdt.h>
|
||||
|
||||
@@ -1178,6 +1179,9 @@ SYSCALL_DEFINE1(rtas, struct rtas_args __user *, uargs)
|
||||
|| nargs + nret > ARRAY_SIZE(args.args))
|
||||
return -EINVAL;
|
||||
|
||||
nargs = array_index_nospec(nargs, ARRAY_SIZE(args.args));
|
||||
nret = array_index_nospec(nret, ARRAY_SIZE(args.args) - nargs);
|
||||
|
||||
/* Copy in args. */
|
||||
if (copy_from_user(args.args, uargs->args,
|
||||
nargs * sizeof(rtas_arg_t)) != 0)
|
||||
|
||||
@@ -1204,7 +1204,13 @@ static void __split_lock_reenable(struct work_struct *work)
|
||||
{
|
||||
sld_update_msr(true);
|
||||
}
|
||||
static DECLARE_DELAYED_WORK(sl_reenable, __split_lock_reenable);
|
||||
/*
|
||||
* In order for each CPU to schedule its delayed work independently of the
|
||||
* others, delayed work struct must be per-CPU. This is not required when
|
||||
* sysctl_sld_mitigate is enabled because of the semaphore that limits
|
||||
* the number of simultaneously scheduled delayed works to 1.
|
||||
*/
|
||||
static DEFINE_PER_CPU(struct delayed_work, sl_reenable);
|
||||
|
||||
/*
|
||||
* If a CPU goes offline with pending delayed work to re-enable split lock
|
||||
@@ -1225,7 +1231,7 @@ static int splitlock_cpu_offline(unsigned int cpu)
|
||||
|
||||
static void split_lock_warn(unsigned long ip)
|
||||
{
|
||||
struct delayed_work *work;
|
||||
struct delayed_work *work = NULL;
|
||||
int cpu;
|
||||
|
||||
if (!current->reported_split_lock)
|
||||
@@ -1247,11 +1253,17 @@ static void split_lock_warn(unsigned long ip)
|
||||
if (down_interruptible(&buslock_sem) == -EINTR)
|
||||
return;
|
||||
work = &sl_reenable_unlock;
|
||||
} else {
|
||||
work = &sl_reenable;
|
||||
}
|
||||
|
||||
cpu = get_cpu();
|
||||
|
||||
if (!work) {
|
||||
work = this_cpu_ptr(&sl_reenable);
|
||||
/* Deferred initialization of per-CPU struct */
|
||||
if (!work->work.func)
|
||||
INIT_DELAYED_WORK(work, __split_lock_reenable);
|
||||
}
|
||||
|
||||
schedule_delayed_work_on(cpu, work, 2);
|
||||
|
||||
/* Disable split lock detection on this CPU to make progress */
|
||||
|
||||
@@ -100,7 +100,12 @@ SYM_CODE_START_LOCAL(pvh_start_xen)
|
||||
xor %edx, %edx
|
||||
wrmsr
|
||||
|
||||
call xen_prepare_pvh
|
||||
/* Call xen_prepare_pvh() via the kernel virtual mapping */
|
||||
leaq xen_prepare_pvh(%rip), %rax
|
||||
subq phys_base(%rip), %rax
|
||||
addq $__START_KERNEL_map, %rax
|
||||
ANNOTATE_RETPOLINE_SAFE
|
||||
call *%rax
|
||||
|
||||
/* startup_64 expects boot_params in %rsi. */
|
||||
mov $_pa(pvh_bootparams), %rsi
|
||||
|
||||
@@ -255,6 +255,7 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct gendisk *disk,
|
||||
blkg->pd[i] = pd;
|
||||
pd->blkg = blkg;
|
||||
pd->plid = i;
|
||||
pd->online = false;
|
||||
}
|
||||
|
||||
return blkg;
|
||||
@@ -326,8 +327,11 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg, struct gendisk *disk,
|
||||
for (i = 0; i < BLKCG_MAX_POLS; i++) {
|
||||
struct blkcg_policy *pol = blkcg_policy[i];
|
||||
|
||||
if (blkg->pd[i] && pol->pd_online_fn)
|
||||
pol->pd_online_fn(blkg->pd[i]);
|
||||
if (blkg->pd[i]) {
|
||||
if (pol->pd_online_fn)
|
||||
pol->pd_online_fn(blkg->pd[i]);
|
||||
blkg->pd[i]->online = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
blkg->online = true;
|
||||
@@ -432,8 +436,11 @@ static void blkg_destroy(struct blkcg_gq *blkg)
|
||||
for (i = 0; i < BLKCG_MAX_POLS; i++) {
|
||||
struct blkcg_policy *pol = blkcg_policy[i];
|
||||
|
||||
if (blkg->pd[i] && pol->pd_offline_fn)
|
||||
pol->pd_offline_fn(blkg->pd[i]);
|
||||
if (blkg->pd[i] && blkg->pd[i]->online) {
|
||||
if (pol->pd_offline_fn)
|
||||
pol->pd_offline_fn(blkg->pd[i]);
|
||||
blkg->pd[i]->online = false;
|
||||
}
|
||||
}
|
||||
|
||||
blkg->online = false;
|
||||
@@ -1422,6 +1429,7 @@ retry:
|
||||
blkg->pd[pol->plid] = pd;
|
||||
pd->blkg = blkg;
|
||||
pd->plid = pol->plid;
|
||||
pd->online = false;
|
||||
}
|
||||
|
||||
/* all allocated, init in the same order */
|
||||
@@ -1429,9 +1437,11 @@ retry:
|
||||
list_for_each_entry_reverse(blkg, &q->blkg_list, q_node)
|
||||
pol->pd_init_fn(blkg->pd[pol->plid]);
|
||||
|
||||
if (pol->pd_online_fn)
|
||||
list_for_each_entry_reverse(blkg, &q->blkg_list, q_node)
|
||||
list_for_each_entry_reverse(blkg, &q->blkg_list, q_node) {
|
||||
if (pol->pd_online_fn)
|
||||
pol->pd_online_fn(blkg->pd[pol->plid]);
|
||||
blkg->pd[pol->plid]->online = true;
|
||||
}
|
||||
|
||||
__set_bit(pol->plid, q->blkcg_pols);
|
||||
ret = 0;
|
||||
@@ -1493,7 +1503,7 @@ void blkcg_deactivate_policy(struct request_queue *q,
|
||||
|
||||
spin_lock(&blkcg->lock);
|
||||
if (blkg->pd[pol->plid]) {
|
||||
if (pol->pd_offline_fn)
|
||||
if (blkg->pd[pol->plid]->online && pol->pd_offline_fn)
|
||||
pol->pd_offline_fn(blkg->pd[pol->plid]);
|
||||
pol->pd_free_fn(blkg->pd[pol->plid]);
|
||||
blkg->pd[pol->plid] = NULL;
|
||||
|
||||
@@ -125,6 +125,7 @@ struct blkg_policy_data {
|
||||
/* the blkg and policy id this per-policy data belongs to */
|
||||
struct blkcg_gq *blkg;
|
||||
int plid;
|
||||
bool online;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -1430,8 +1430,11 @@ static void iocg_pay_debt(struct ioc_gq *iocg, u64 abs_vpay,
|
||||
lockdep_assert_held(&iocg->ioc->lock);
|
||||
lockdep_assert_held(&iocg->waitq.lock);
|
||||
|
||||
/* make sure that nobody messed with @iocg */
|
||||
WARN_ON_ONCE(list_empty(&iocg->active_list));
|
||||
/*
|
||||
* make sure that nobody messed with @iocg. Check iocg->pd.online
|
||||
* to avoid warn when removing blkcg or disk.
|
||||
*/
|
||||
WARN_ON_ONCE(list_empty(&iocg->active_list) && iocg->pd.online);
|
||||
WARN_ON_ONCE(iocg->inuse > 1);
|
||||
|
||||
iocg->abs_vdebt -= min(abs_vpay, iocg->abs_vdebt);
|
||||
|
||||
@@ -2698,10 +2698,18 @@ EXPORT_SYMBOL(cpufreq_update_policy);
|
||||
*/
|
||||
void cpufreq_update_limits(unsigned int cpu)
|
||||
{
|
||||
struct cpufreq_policy *policy;
|
||||
|
||||
policy = cpufreq_cpu_get(cpu);
|
||||
if (!policy)
|
||||
return;
|
||||
|
||||
if (cpufreq_driver->update_limits)
|
||||
cpufreq_driver->update_limits(cpu);
|
||||
else
|
||||
cpufreq_update_policy(cpu);
|
||||
|
||||
cpufreq_cpu_put(policy);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpufreq_update_limits);
|
||||
|
||||
|
||||
@@ -4499,17 +4499,17 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
|
||||
if (link_cnt > (MAX_PIPES * 2)) {
|
||||
DRM_ERROR(
|
||||
"KMS: Cannot support more than %d display indexes\n",
|
||||
MAX_PIPES * 2);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* loops over all connectors on the board */
|
||||
for (i = 0; i < link_cnt; i++) {
|
||||
struct dc_link *link = NULL;
|
||||
|
||||
if (i > AMDGPU_DM_MAX_DISPLAY_INDEX) {
|
||||
DRM_ERROR(
|
||||
"KMS: Cannot support more than %d display indexes\n",
|
||||
AMDGPU_DM_MAX_DISPLAY_INDEX);
|
||||
continue;
|
||||
}
|
||||
|
||||
aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL);
|
||||
if (!aconnector)
|
||||
goto fail;
|
||||
|
||||
@@ -1192,7 +1192,8 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
/* clang stack usage explodes if this is inlined */
|
||||
static noinline_for_stack
|
||||
void vdec_vp9_slice_map_counts_eob_coef(unsigned int i, unsigned int j, unsigned int k,
|
||||
struct vdec_vp9_slice_frame_counts *counts,
|
||||
struct v4l2_vp9_frame_symbol_counts *counts_helper)
|
||||
|
||||
@@ -245,7 +245,7 @@ static bool pci_endpoint_test_request_irq(struct pci_endpoint_test *test)
|
||||
return true;
|
||||
|
||||
fail:
|
||||
switch (irq_type) {
|
||||
switch (test->irq_type) {
|
||||
case IRQ_TYPE_LEGACY:
|
||||
dev_err(dev, "Failed to request IRQ %d for Legacy\n",
|
||||
pci_irq_vector(pdev, i));
|
||||
@@ -262,6 +262,9 @@ fail:
|
||||
break;
|
||||
}
|
||||
|
||||
test->num_irqs = i;
|
||||
pci_endpoint_test_release_irq(test);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -714,6 +717,7 @@ static bool pci_endpoint_test_set_irq(struct pci_endpoint_test *test,
|
||||
if (!pci_endpoint_test_request_irq(test))
|
||||
goto err;
|
||||
|
||||
irq_type = test->irq_type;
|
||||
return true;
|
||||
|
||||
err:
|
||||
|
||||
@@ -173,20 +173,6 @@ struct nvmet_fc_tgt_assoc {
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
|
||||
|
||||
static inline int
|
||||
nvmet_fc_iodnum(struct nvmet_fc_ls_iod *iodptr)
|
||||
{
|
||||
return (iodptr - iodptr->tgtport->iod);
|
||||
}
|
||||
|
||||
static inline int
|
||||
nvmet_fc_fodnum(struct nvmet_fc_fcp_iod *fodptr)
|
||||
{
|
||||
return (fodptr - fodptr->queue->fod);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Association and Connection IDs:
|
||||
*
|
||||
|
||||
@@ -112,7 +112,7 @@ static int is_xen_swiotlb_buffer(struct device *dev, dma_addr_t dma_addr)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
int __init xen_swiotlb_fixup(void *buf, unsigned long nslabs)
|
||||
int xen_swiotlb_fixup(void *buf, unsigned long nslabs)
|
||||
{
|
||||
int rc;
|
||||
unsigned int order = get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT);
|
||||
|
||||
@@ -1428,6 +1428,7 @@ out_unlock:
|
||||
locked_page,
|
||||
clear_bits,
|
||||
page_ops);
|
||||
btrfs_qgroup_free_data(inode, NULL, start, cur_alloc_size, NULL);
|
||||
start += cur_alloc_size;
|
||||
}
|
||||
|
||||
@@ -1441,6 +1442,7 @@ out_unlock:
|
||||
clear_bits |= EXTENT_CLEAR_DATA_RESV;
|
||||
extent_clear_unlock_delalloc(inode, start, end, locked_page,
|
||||
clear_bits, page_ops);
|
||||
btrfs_qgroup_free_data(inode, NULL, start, end - start + 1, NULL);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -2168,13 +2170,15 @@ error:
|
||||
if (nocow)
|
||||
btrfs_dec_nocow_writers(bg);
|
||||
|
||||
if (ret && cur_offset < end)
|
||||
if (ret && cur_offset < end) {
|
||||
extent_clear_unlock_delalloc(inode, cur_offset, end,
|
||||
locked_page, EXTENT_LOCKED |
|
||||
EXTENT_DELALLOC | EXTENT_DEFRAG |
|
||||
EXTENT_DO_ACCOUNTING, PAGE_UNLOCK |
|
||||
PAGE_START_WRITEBACK |
|
||||
PAGE_END_WRITEBACK);
|
||||
btrfs_qgroup_free_data(inode, NULL, cur_offset, end - cur_offset + 1, NULL);
|
||||
}
|
||||
btrfs_free_path(path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1909,6 +1909,9 @@ bool btrfs_zone_activate(struct btrfs_block_group *block_group)
|
||||
device = map->stripes[i].dev;
|
||||
physical = map->stripes[i].physical;
|
||||
|
||||
if (!device->bdev)
|
||||
continue;
|
||||
|
||||
if (device->zone_info->max_active_zones == 0)
|
||||
continue;
|
||||
|
||||
@@ -2052,6 +2055,9 @@ static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_writ
|
||||
struct btrfs_device *device = map->stripes[i].dev;
|
||||
const u64 physical = map->stripes[i].physical;
|
||||
|
||||
if (!device->bdev)
|
||||
continue;
|
||||
|
||||
if (device->zone_info->max_active_zones == 0)
|
||||
continue;
|
||||
|
||||
|
||||
@@ -258,6 +258,31 @@ compose_mount_options_err:
|
||||
goto compose_mount_options_out;
|
||||
}
|
||||
|
||||
static int set_dest_addr(struct smb3_fs_context *ctx, const char *full_path)
|
||||
{
|
||||
struct sockaddr *addr = (struct sockaddr *)&ctx->dstaddr;
|
||||
char *str_addr = NULL;
|
||||
int rc;
|
||||
|
||||
rc = dns_resolve_server_name_to_ip(full_path, &str_addr, NULL);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
rc = cifs_convert_address(addr, str_addr, strlen(str_addr));
|
||||
if (!rc) {
|
||||
cifs_dbg(FYI, "%s: failed to convert ip address\n", __func__);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cifs_set_port(addr, ctx->port);
|
||||
rc = 0;
|
||||
|
||||
out:
|
||||
kfree(str_addr);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a vfsmount that we can automount
|
||||
*/
|
||||
@@ -295,8 +320,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct path *path)
|
||||
ctx = smb3_fc2context(fc);
|
||||
|
||||
page = alloc_dentry_path();
|
||||
/* always use tree name prefix */
|
||||
full_path = build_path_from_dentry_optional_prefix(mntpt, page, true);
|
||||
full_path = dfs_get_automount_devname(mntpt, page);
|
||||
if (IS_ERR(full_path)) {
|
||||
mnt = ERR_CAST(full_path);
|
||||
goto out;
|
||||
@@ -315,6 +339,12 @@ static struct vfsmount *cifs_dfs_do_automount(struct path *path)
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = set_dest_addr(ctx, full_path);
|
||||
if (rc) {
|
||||
mnt = ERR_PTR(rc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = smb3_parse_devname(full_path, ctx);
|
||||
if (!rc)
|
||||
mnt = fc_mount(fc);
|
||||
|
||||
@@ -57,8 +57,29 @@ extern void exit_cifs_idmap(void);
|
||||
extern int init_cifs_spnego(void);
|
||||
extern void exit_cifs_spnego(void);
|
||||
extern const char *build_path_from_dentry(struct dentry *, void *);
|
||||
char *__build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
|
||||
const char *tree, int tree_len,
|
||||
bool prefix);
|
||||
extern char *build_path_from_dentry_optional_prefix(struct dentry *direntry,
|
||||
void *page, bool prefix);
|
||||
|
||||
#ifdef CONFIG_CIFS_DFS_UPCALL
|
||||
static inline char *dfs_get_automount_devname(struct dentry *dentry, void *page)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
|
||||
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
struct TCP_Server_Info *server = tcon->ses->server;
|
||||
|
||||
if (unlikely(!server->origin_fullpath))
|
||||
return ERR_PTR(-EREMOTE);
|
||||
|
||||
return __build_path_from_dentry_optional_prefix(dentry, page,
|
||||
server->origin_fullpath,
|
||||
strlen(server->origin_fullpath),
|
||||
true);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void *alloc_dentry_path(void)
|
||||
{
|
||||
return __getname();
|
||||
|
||||
@@ -78,14 +78,13 @@ build_path_from_dentry(struct dentry *direntry, void *page)
|
||||
prefix);
|
||||
}
|
||||
|
||||
char *
|
||||
build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
|
||||
bool prefix)
|
||||
char *__build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
|
||||
const char *tree, int tree_len,
|
||||
bool prefix)
|
||||
{
|
||||
int dfsplen;
|
||||
int pplen = 0;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
|
||||
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
char dirsep = CIFS_DIR_SEP(cifs_sb);
|
||||
char *s;
|
||||
|
||||
@@ -93,7 +92,7 @@ build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
if (prefix)
|
||||
dfsplen = strnlen(tcon->tree_name, MAX_TREE_SIZE + 1);
|
||||
dfsplen = strnlen(tree, tree_len + 1);
|
||||
else
|
||||
dfsplen = 0;
|
||||
|
||||
@@ -123,7 +122,7 @@ build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
|
||||
}
|
||||
if (dfsplen) {
|
||||
s -= dfsplen;
|
||||
memcpy(s, tcon->tree_name, dfsplen);
|
||||
memcpy(s, tree, dfsplen);
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
|
||||
int i;
|
||||
for (i = 0; i < dfsplen; i++) {
|
||||
@@ -135,6 +134,16 @@ build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
|
||||
return s;
|
||||
}
|
||||
|
||||
char *build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
|
||||
bool prefix)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
|
||||
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
|
||||
return __build_path_from_dentry_optional_prefix(direntry, page, tcon->tree_name,
|
||||
MAX_TREE_SIZE, prefix);
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't allow path components longer than the server max.
|
||||
* Don't allow the separator character in a path component.
|
||||
|
||||
@@ -1515,7 +1515,7 @@ void create_lease_buf(u8 *rbuf, struct lease *lease)
|
||||
* @open_req: buffer containing smb2 file open(create) request
|
||||
* @is_dir: whether leasing file is directory
|
||||
*
|
||||
* Return: oplock state, -ENOENT if create lease context not found
|
||||
* Return: allocated lease context object on success, otherwise NULL
|
||||
*/
|
||||
struct lease_ctx_info *parse_lease_state(void *open_req, bool is_dir)
|
||||
{
|
||||
|
||||
@@ -3243,7 +3243,7 @@ int smb2_open(struct ksmbd_work *work)
|
||||
goto err_out1;
|
||||
}
|
||||
} else {
|
||||
if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE) {
|
||||
if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE && lc) {
|
||||
/*
|
||||
* Compare parent lease using parent key. If there is no
|
||||
* a lease that has same parent key, Send lease break
|
||||
|
||||
@@ -246,6 +246,7 @@ struct bpf_map {
|
||||
* same prog type, JITed flag and xdp_has_frags flag.
|
||||
*/
|
||||
struct {
|
||||
const struct btf_type *attach_func_proto;
|
||||
spinlock_t lock;
|
||||
enum bpf_prog_type type;
|
||||
bool jited;
|
||||
|
||||
@@ -38,9 +38,11 @@ struct landlock_ruleset_attr {
|
||||
*
|
||||
* - %LANDLOCK_CREATE_RULESET_VERSION: Get the highest supported Landlock ABI
|
||||
* version.
|
||||
* - %LANDLOCK_CREATE_RULESET_ERRATA: Get a bitmask of fixed issues.
|
||||
*/
|
||||
/* clang-format off */
|
||||
#define LANDLOCK_CREATE_RULESET_VERSION (1U << 0)
|
||||
#define LANDLOCK_CREATE_RULESET_ERRATA (1U << 1)
|
||||
/* clang-format on */
|
||||
|
||||
/**
|
||||
|
||||
@@ -2104,6 +2104,7 @@ bool bpf_prog_map_compatible(struct bpf_map *map,
|
||||
{
|
||||
enum bpf_prog_type prog_type = resolve_prog_type(fp);
|
||||
bool ret;
|
||||
struct bpf_prog_aux *aux = fp->aux;
|
||||
|
||||
if (fp->kprobe_override)
|
||||
return false;
|
||||
@@ -2115,12 +2116,26 @@ bool bpf_prog_map_compatible(struct bpf_map *map,
|
||||
*/
|
||||
map->owner.type = prog_type;
|
||||
map->owner.jited = fp->jited;
|
||||
map->owner.xdp_has_frags = fp->aux->xdp_has_frags;
|
||||
map->owner.xdp_has_frags = aux->xdp_has_frags;
|
||||
map->owner.attach_func_proto = aux->attach_func_proto;
|
||||
ret = true;
|
||||
} else {
|
||||
ret = map->owner.type == prog_type &&
|
||||
map->owner.jited == fp->jited &&
|
||||
map->owner.xdp_has_frags == fp->aux->xdp_has_frags;
|
||||
map->owner.xdp_has_frags == aux->xdp_has_frags;
|
||||
if (ret &&
|
||||
map->owner.attach_func_proto != aux->attach_func_proto) {
|
||||
switch (prog_type) {
|
||||
case BPF_PROG_TYPE_TRACING:
|
||||
case BPF_PROG_TYPE_LSM:
|
||||
case BPF_PROG_TYPE_EXT:
|
||||
case BPF_PROG_TYPE_STRUCT_OPS:
|
||||
ret = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock(&map->owner.lock);
|
||||
|
||||
|
||||
@@ -793,7 +793,7 @@ static const struct vm_operations_struct bpf_map_default_vmops = {
|
||||
static int bpf_map_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
struct bpf_map *map = filp->private_data;
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
if (!map->ops->map_mmap || map_value_has_spin_lock(map) ||
|
||||
map_value_has_timer(map) || map_value_has_kptrs(map))
|
||||
@@ -818,7 +818,12 @@ static int bpf_map_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
err = -EACCES;
|
||||
goto out;
|
||||
}
|
||||
bpf_map_write_active_inc(map);
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&map->freeze_mutex);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* set default open/close callbacks */
|
||||
vma->vm_ops = &bpf_map_default_vmops;
|
||||
@@ -829,13 +834,11 @@ static int bpf_map_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
vm_flags_clear(vma, VM_MAYWRITE);
|
||||
|
||||
err = map->ops->map_mmap(map, vma);
|
||||
if (err)
|
||||
goto out;
|
||||
if (err) {
|
||||
if (vma->vm_flags & VM_WRITE)
|
||||
bpf_map_write_active_dec(map);
|
||||
}
|
||||
|
||||
if (vma->vm_flags & VM_MAYWRITE)
|
||||
bpf_map_write_active_inc(map);
|
||||
out:
|
||||
mutex_unlock(&map->freeze_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
2
mm/gup.c
2
mm/gup.c
@@ -232,7 +232,7 @@ bool __must_check try_grab_page(struct page *page, unsigned int flags)
|
||||
* and it is used in a *lot* of places.
|
||||
*/
|
||||
if (is_zero_page(page))
|
||||
return 0;
|
||||
return true;
|
||||
|
||||
/*
|
||||
* Similar to try_grab_folio(): be sure to *also*
|
||||
|
||||
@@ -2684,11 +2684,11 @@ static int apply_to_pte_range(struct mm_struct *mm, pmd_t *pmd,
|
||||
if (fn) {
|
||||
do {
|
||||
if (create || !pte_none(*pte)) {
|
||||
err = fn(pte++, addr, data);
|
||||
err = fn(pte, addr, data);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
} while (addr += PAGE_SIZE, addr != end);
|
||||
} while (pte++, addr += PAGE_SIZE, addr != end);
|
||||
}
|
||||
*mask |= PGTBL_PTE_MODIFIED;
|
||||
|
||||
|
||||
@@ -1266,6 +1266,12 @@ static int mptcp_getsockopt_v4(struct mptcp_sock *msk, int optname,
|
||||
switch (optname) {
|
||||
case IP_TOS:
|
||||
return mptcp_put_int_option(msk, optval, optlen, inet_sk(sk)->tos);
|
||||
case IP_FREEBIND:
|
||||
return mptcp_put_int_option(msk, optval, optlen,
|
||||
inet_sk(sk)->freebind);
|
||||
case IP_TRANSPARENT:
|
||||
return mptcp_put_int_option(msk, optval, optlen,
|
||||
inet_sk(sk)->transparent);
|
||||
}
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
@@ -1280,6 +1286,12 @@ static int mptcp_getsockopt_v6(struct mptcp_sock *msk, int optname,
|
||||
case IPV6_V6ONLY:
|
||||
return mptcp_put_int_option(msk, optval, optlen,
|
||||
sk->sk_ipv6only);
|
||||
case IPV6_TRANSPARENT:
|
||||
return mptcp_put_int_option(msk, optval, optlen,
|
||||
inet_sk(sk)->transparent);
|
||||
case IPV6_FREEBIND:
|
||||
return mptcp_put_int_option(msk, optval, optlen,
|
||||
inet_sk(sk)->freebind);
|
||||
}
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
87
security/landlock/errata.h
Normal file
87
security/landlock/errata.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Landlock - Errata information
|
||||
*
|
||||
* Copyright © 2025 Microsoft Corporation
|
||||
*/
|
||||
|
||||
#ifndef _SECURITY_LANDLOCK_ERRATA_H
|
||||
#define _SECURITY_LANDLOCK_ERRATA_H
|
||||
|
||||
#include <linux/init.h>
|
||||
|
||||
struct landlock_erratum {
|
||||
const int abi;
|
||||
const u8 number;
|
||||
};
|
||||
|
||||
/* clang-format off */
|
||||
#define LANDLOCK_ERRATUM(NUMBER) \
|
||||
{ \
|
||||
.abi = LANDLOCK_ERRATA_ABI, \
|
||||
.number = NUMBER, \
|
||||
},
|
||||
/* clang-format on */
|
||||
|
||||
/*
|
||||
* Some fixes may require user space to check if they are applied on the running
|
||||
* kernel before using a specific feature. For instance, this applies when a
|
||||
* restriction was previously too restrictive and is now getting relaxed (for
|
||||
* compatibility or semantic reasons). However, non-visible changes for
|
||||
* legitimate use (e.g. security fixes) do not require an erratum.
|
||||
*/
|
||||
static const struct landlock_erratum landlock_errata_init[] __initconst = {
|
||||
|
||||
/*
|
||||
* Only Sparse may not implement __has_include. If a compiler does not
|
||||
* implement __has_include, a warning will be printed at boot time (see
|
||||
* setup.c).
|
||||
*/
|
||||
#ifdef __has_include
|
||||
|
||||
#define LANDLOCK_ERRATA_ABI 1
|
||||
#if __has_include("errata/abi-1.h")
|
||||
#include "errata/abi-1.h"
|
||||
#endif
|
||||
#undef LANDLOCK_ERRATA_ABI
|
||||
|
||||
#define LANDLOCK_ERRATA_ABI 2
|
||||
#if __has_include("errata/abi-2.h")
|
||||
#include "errata/abi-2.h"
|
||||
#endif
|
||||
#undef LANDLOCK_ERRATA_ABI
|
||||
|
||||
#define LANDLOCK_ERRATA_ABI 3
|
||||
#if __has_include("errata/abi-3.h")
|
||||
#include "errata/abi-3.h"
|
||||
#endif
|
||||
#undef LANDLOCK_ERRATA_ABI
|
||||
|
||||
#define LANDLOCK_ERRATA_ABI 4
|
||||
#if __has_include("errata/abi-4.h")
|
||||
#include "errata/abi-4.h"
|
||||
#endif
|
||||
#undef LANDLOCK_ERRATA_ABI
|
||||
|
||||
/*
|
||||
* For each new erratum, we need to include all the ABI files up to the impacted
|
||||
* ABI to make all potential future intermediate errata easy to backport.
|
||||
*
|
||||
* If such change involves more than one ABI addition, then it must be in a
|
||||
* dedicated commit with the same Fixes tag as used for the actual fix.
|
||||
*
|
||||
* Each commit creating a new security/landlock/errata/abi-*.h file must have a
|
||||
* Depends-on tag to reference the commit that previously added the line to
|
||||
* include this new file, except if the original Fixes tag is enough.
|
||||
*
|
||||
* Each erratum must be documented in its related ABI file, and a dedicated
|
||||
* commit must update Documentation/userspace-api/landlock.rst to include this
|
||||
* erratum. This commit will not be backported.
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
{}
|
||||
};
|
||||
|
||||
#endif /* _SECURITY_LANDLOCK_ERRATA_H */
|
||||
@@ -6,11 +6,13 @@
|
||||
* Copyright © 2018-2020 ANSSI
|
||||
*/
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/lsm_hooks.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "cred.h"
|
||||
#include "errata.h"
|
||||
#include "fs.h"
|
||||
#include "ptrace.h"
|
||||
#include "setup.h"
|
||||
@@ -23,8 +25,36 @@ struct lsm_blob_sizes landlock_blob_sizes __lsm_ro_after_init = {
|
||||
.lbs_superblock = sizeof(struct landlock_superblock_security),
|
||||
};
|
||||
|
||||
int landlock_errata __ro_after_init;
|
||||
|
||||
static void __init compute_errata(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
#ifndef __has_include
|
||||
/*
|
||||
* This is a safeguard to make sure the compiler implements
|
||||
* __has_include (see errata.h).
|
||||
*/
|
||||
WARN_ON_ONCE(1);
|
||||
return;
|
||||
#endif
|
||||
|
||||
for (i = 0; landlock_errata_init[i].number; i++) {
|
||||
const int prev_errata = landlock_errata;
|
||||
|
||||
if (WARN_ON_ONCE(landlock_errata_init[i].abi >
|
||||
landlock_abi_version))
|
||||
continue;
|
||||
|
||||
landlock_errata |= BIT(landlock_errata_init[i].number - 1);
|
||||
WARN_ON_ONCE(prev_errata == landlock_errata);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init landlock_init(void)
|
||||
{
|
||||
compute_errata();
|
||||
landlock_add_cred_hooks();
|
||||
landlock_add_ptrace_hooks();
|
||||
landlock_add_fs_hooks();
|
||||
|
||||
@@ -11,7 +11,10 @@
|
||||
|
||||
#include <linux/lsm_hooks.h>
|
||||
|
||||
extern const int landlock_abi_version;
|
||||
|
||||
extern bool landlock_initialized;
|
||||
extern int landlock_errata;
|
||||
|
||||
extern struct lsm_blob_sizes landlock_blob_sizes;
|
||||
|
||||
|
||||
@@ -150,7 +150,9 @@ static const struct file_operations ruleset_fops = {
|
||||
* the new ruleset.
|
||||
* @size: Size of the pointed &struct landlock_ruleset_attr (needed for
|
||||
* backward and forward compatibility).
|
||||
* @flags: Supported value: %LANDLOCK_CREATE_RULESET_VERSION.
|
||||
* @flags: Supported value:
|
||||
* - %LANDLOCK_CREATE_RULESET_VERSION
|
||||
* - %LANDLOCK_CREATE_RULESET_ERRATA
|
||||
*
|
||||
* This system call enables to create a new Landlock ruleset, and returns the
|
||||
* related file descriptor on success.
|
||||
@@ -159,6 +161,10 @@ static const struct file_operations ruleset_fops = {
|
||||
* 0, then the returned value is the highest supported Landlock ABI version
|
||||
* (starting at 1).
|
||||
*
|
||||
* If @flags is %LANDLOCK_CREATE_RULESET_ERRATA and @attr is NULL and @size is
|
||||
* 0, then the returned value is a bitmask of fixed issues for the current
|
||||
* Landlock ABI version.
|
||||
*
|
||||
* Possible returned errors are:
|
||||
*
|
||||
* - %EOPNOTSUPP: Landlock is supported by the kernel but disabled at boot time;
|
||||
@@ -181,9 +187,15 @@ SYSCALL_DEFINE3(landlock_create_ruleset,
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (flags) {
|
||||
if ((flags == LANDLOCK_CREATE_RULESET_VERSION) && !attr &&
|
||||
!size)
|
||||
return LANDLOCK_ABI_VERSION;
|
||||
if (attr || size)
|
||||
return -EINVAL;
|
||||
|
||||
if (flags == LANDLOCK_CREATE_RULESET_VERSION)
|
||||
return landlock_abi_version;
|
||||
|
||||
if (flags == LANDLOCK_CREATE_RULESET_ERRATA)
|
||||
return landlock_errata;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -213,6 +225,8 @@ SYSCALL_DEFINE3(landlock_create_ruleset,
|
||||
return ruleset_fd;
|
||||
}
|
||||
|
||||
const int landlock_abi_version = LANDLOCK_ABI_VERSION;
|
||||
|
||||
/*
|
||||
* Returns an owned ruleset from a FD. It is thus needed to call
|
||||
* landlock_put_ruleset() on the return value.
|
||||
|
||||
@@ -98,10 +98,54 @@ TEST(abi_version)
|
||||
ASSERT_EQ(EINVAL, errno);
|
||||
}
|
||||
|
||||
/*
|
||||
* Old source trees might not have the set of Kselftest fixes related to kernel
|
||||
* UAPI headers.
|
||||
*/
|
||||
#ifndef LANDLOCK_CREATE_RULESET_ERRATA
|
||||
#define LANDLOCK_CREATE_RULESET_ERRATA (1U << 1)
|
||||
#endif
|
||||
|
||||
TEST(errata)
|
||||
{
|
||||
const struct landlock_ruleset_attr ruleset_attr = {
|
||||
.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE,
|
||||
};
|
||||
int errata;
|
||||
|
||||
errata = landlock_create_ruleset(NULL, 0,
|
||||
LANDLOCK_CREATE_RULESET_ERRATA);
|
||||
/* The errata bitmask will not be backported to tests. */
|
||||
ASSERT_LE(0, errata);
|
||||
TH_LOG("errata: 0x%x", errata);
|
||||
|
||||
ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 0,
|
||||
LANDLOCK_CREATE_RULESET_ERRATA));
|
||||
ASSERT_EQ(EINVAL, errno);
|
||||
|
||||
ASSERT_EQ(-1, landlock_create_ruleset(NULL, sizeof(ruleset_attr),
|
||||
LANDLOCK_CREATE_RULESET_ERRATA));
|
||||
ASSERT_EQ(EINVAL, errno);
|
||||
|
||||
ASSERT_EQ(-1,
|
||||
landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr),
|
||||
LANDLOCK_CREATE_RULESET_ERRATA));
|
||||
ASSERT_EQ(EINVAL, errno);
|
||||
|
||||
ASSERT_EQ(-1, landlock_create_ruleset(
|
||||
NULL, 0,
|
||||
LANDLOCK_CREATE_RULESET_VERSION |
|
||||
LANDLOCK_CREATE_RULESET_ERRATA));
|
||||
ASSERT_EQ(-1, landlock_create_ruleset(NULL, 0,
|
||||
LANDLOCK_CREATE_RULESET_ERRATA |
|
||||
1 << 31));
|
||||
ASSERT_EQ(EINVAL, errno);
|
||||
}
|
||||
|
||||
/* Tests ordering of syscall argument checks. */
|
||||
TEST(create_ruleset_checks_ordering)
|
||||
{
|
||||
const int last_flag = LANDLOCK_CREATE_RULESET_VERSION;
|
||||
const int last_flag = LANDLOCK_CREATE_RULESET_ERRATA;
|
||||
const int invalid_flag = last_flag << 1;
|
||||
int ruleset_fd;
|
||||
const struct landlock_ruleset_attr ruleset_attr = {
|
||||
|
||||
Reference in New Issue
Block a user