There are no significant series in this small merge. Please see the

individual changelogs for details.
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYIAB0WIQTTMBEPP41GrTpTJgfdBJ7gKXxAjgUCaTsgBwAKCRDdBJ7gKXxA
 jkSIAP4jD66nEC2QyKTiv9XvXi8rpKz6RGAHNZSam0ucI5WKswEAoflmlqsoD/Kk
 sN3YLwLztzCJIYU7tT3IRaPK0irwDAo=
 =nkux
 -----END PGP SIGNATURE-----

Merge tag 'mm-nonmm-stable-2025-12-11-11-47' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm

Pull misc updates from Andrew Morton:
 "There are no significant series in this small merge. Please see the
  individual changelogs for details"

[ Editor's note: it's mainly ocfs2 and a couple of random fixes ]

* tag 'mm-nonmm-stable-2025-12-11-11-47' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm:
  mm: memfd_luo: add CONFIG_SHMEM dependency
  mm: shmem: avoid build warning for CONFIG_SHMEM=n
  ocfs2: fix memory leak in ocfs2_merge_rec_left()
  ocfs2: invalidate inode if i_mode is zero after block read
  ocfs2: avoid -Wflex-array-member-not-at-end warning
  ocfs2: convert remaining read-only checks to ocfs2_emergency_state
  ocfs2: add ocfs2_emergency_state helper and apply to setattr
  checkpatch: add uninitialized pointer with __free attribute check
  args: fix documentation to reflect the correct numbers
  ocfs2: fix kernel BUG in ocfs2_find_victim_chain
  liveupdate: luo_core: fix redundant bound check in luo_ioctl()
  ocfs2: validate inline xattr size and entry count in ocfs2_xattr_ibody_list
  fs/fat: remove unnecessary wrapper fat_max_cache()
  ocfs2: replace deprecated strcpy with strscpy
  ocfs2: check tl_used after reading it from trancate log inode
  liveupdate: luo_file: don't use invalid list iterator
master
Linus Torvalds 2025-12-13 20:55:12 +12:00
commit 9d9c1cfec0
22 changed files with 154 additions and 44 deletions

View File

@ -1002,6 +1002,29 @@ Functions and Variables
return bar; return bar;
**UNINITIALIZED_PTR_WITH_FREE**
Pointers with __free attribute should be declared at the place of use
and initialized (see include/linux/cleanup.h). In this case
declarations at the top of the function rule can be relaxed. Not doing
so may lead to undefined behavior as the memory assigned (garbage,
in case not initialized) to the pointer is freed automatically when
the pointer goes out of scope.
Also see: https://lore.kernel.org/lkml/58fd478f408a34b578ee8d949c5c4b4da4d4f41d.camel@HansenPartnership.com/
Example::
type var __free(free_func);
... // var not used, but, in future someone might add a return here
var = malloc(var_size);
...
should be initialized as::
...
type var __free(free_func) = malloc(var_size);
...
Permissions Permissions
----------- -----------

View File

@ -29,11 +29,6 @@ struct fat_cache_id {
int dcluster; int dcluster;
}; };
static inline int fat_max_cache(struct inode *inode)
{
return FAT_MAX_CACHE;
}
static struct kmem_cache *fat_cache_cachep; static struct kmem_cache *fat_cache_cachep;
static void init_once(void *foo) static void init_once(void *foo)
@ -145,7 +140,7 @@ static void fat_cache_add(struct inode *inode, struct fat_cache_id *new)
cache = fat_cache_merge(inode, new); cache = fat_cache_merge(inode, new);
if (cache == NULL) { if (cache == NULL) {
if (MSDOS_I(inode)->nr_caches < fat_max_cache(inode)) { if (MSDOS_I(inode)->nr_caches < FAT_MAX_CACHE) {
MSDOS_I(inode)->nr_caches++; MSDOS_I(inode)->nr_caches++;
spin_unlock(&MSDOS_I(inode)->cache_lru_lock); spin_unlock(&MSDOS_I(inode)->cache_lru_lock);

View File

@ -10,6 +10,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h>
#include <linux/highmem.h> #include <linux/highmem.h>
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/quotaops.h> #include <linux/quotaops.h>
@ -1037,7 +1038,7 @@ static int ocfs2_create_new_meta_bhs(handle_t *handle,
memset(bhs[i]->b_data, 0, osb->sb->s_blocksize); memset(bhs[i]->b_data, 0, osb->sb->s_blocksize);
eb = (struct ocfs2_extent_block *) bhs[i]->b_data; eb = (struct ocfs2_extent_block *) bhs[i]->b_data;
/* Ok, setup the minimal stuff here. */ /* Ok, setup the minimal stuff here. */
strcpy(eb->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE); strscpy(eb->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE);
eb->h_blkno = cpu_to_le64(first_blkno); eb->h_blkno = cpu_to_le64(first_blkno);
eb->h_fs_generation = cpu_to_le32(osb->fs_generation); eb->h_fs_generation = cpu_to_le32(osb->fs_generation);
eb->h_suballoc_slot = eb->h_suballoc_slot =
@ -3654,7 +3655,6 @@ static int ocfs2_merge_rec_left(struct ocfs2_path *right_path,
* So we use the new rightmost path. * So we use the new rightmost path.
*/ */
ocfs2_mv_path(right_path, left_path); ocfs2_mv_path(right_path, left_path);
left_path = NULL;
} else } else
ocfs2_complete_edge_insert(handle, left_path, ocfs2_complete_edge_insert(handle, left_path,
right_path, subtree_index); right_path, subtree_index);
@ -6164,7 +6164,7 @@ static int ocfs2_get_truncate_log_info(struct ocfs2_super *osb,
struct buffer_head *bh = NULL; struct buffer_head *bh = NULL;
struct ocfs2_dinode *di; struct ocfs2_dinode *di;
struct ocfs2_truncate_log *tl; struct ocfs2_truncate_log *tl;
unsigned int tl_count; unsigned int tl_count, tl_used;
inode = ocfs2_get_system_file_inode(osb, inode = ocfs2_get_system_file_inode(osb,
TRUNCATE_LOG_SYSTEM_INODE, TRUNCATE_LOG_SYSTEM_INODE,
@ -6185,8 +6185,10 @@ static int ocfs2_get_truncate_log_info(struct ocfs2_super *osb,
di = (struct ocfs2_dinode *)bh->b_data; di = (struct ocfs2_dinode *)bh->b_data;
tl = &di->id2.i_dealloc; tl = &di->id2.i_dealloc;
tl_count = le16_to_cpu(tl->tl_count); tl_count = le16_to_cpu(tl->tl_count);
tl_used = le16_to_cpu(tl->tl_used);
if (unlikely(tl_count > ocfs2_truncate_recs_per_inode(osb->sb) || if (unlikely(tl_count > ocfs2_truncate_recs_per_inode(osb->sb) ||
tl_count == 0)) { tl_count == 0 ||
tl_used > tl_count)) {
status = -EFSCORRUPTED; status = -EFSCORRUPTED;
iput(inode); iput(inode);
brelse(bh); brelse(bh);
@ -6744,7 +6746,7 @@ static int ocfs2_reuse_blk_from_dealloc(handle_t *handle,
/* We can't guarantee that buffer head is still cached, so /* We can't guarantee that buffer head is still cached, so
* polutlate the extent block again. * polutlate the extent block again.
*/ */
strcpy(eb->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE); strscpy(eb->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE);
eb->h_blkno = cpu_to_le64(bf->free_blk); eb->h_blkno = cpu_to_le64(bf->free_blk);
eb->h_fs_generation = cpu_to_le32(osb->fs_generation); eb->h_fs_generation = cpu_to_le32(osb->fs_generation);
eb->h_suballoc_slot = cpu_to_le16(real_slot); eb->h_suballoc_slot = cpu_to_le16(real_slot);

View File

@ -434,7 +434,7 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb,
BUG_ON(buffer_jbd(bh)); BUG_ON(buffer_jbd(bh));
ocfs2_check_super_or_backup(osb->sb, bh->b_blocknr); ocfs2_check_super_or_backup(osb->sb, bh->b_blocknr);
if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) { if (unlikely(ocfs2_emergency_state(osb))) {
ret = -EROFS; ret = -EROFS;
mlog_errno(ret); mlog_errno(ret);
goto out; goto out;

View File

@ -4,6 +4,7 @@
*/ */
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/configfs.h> #include <linux/configfs.h>
@ -590,7 +591,7 @@ static struct config_item *o2nm_node_group_make_item(struct config_group *group,
if (node == NULL) if (node == NULL)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
strcpy(node->nd_name, name); /* use item.ci_namebuf instead? */ strscpy(node->nd_name, name); /* use item.ci_namebuf instead? */
config_item_init_type_name(&node->nd_item, name, &o2nm_node_type); config_item_init_type_name(&node->nd_item, name, &o2nm_node_type);
spin_lock_init(&node->nd_lock); spin_lock_init(&node->nd_lock);

View File

@ -136,7 +136,7 @@ static void ocfs2_init_dir_trailer(struct inode *inode,
struct ocfs2_dir_block_trailer *trailer; struct ocfs2_dir_block_trailer *trailer;
trailer = ocfs2_trailer_from_bh(bh, inode->i_sb); trailer = ocfs2_trailer_from_bh(bh, inode->i_sb);
strcpy(trailer->db_signature, OCFS2_DIR_TRAILER_SIGNATURE); strscpy(trailer->db_signature, OCFS2_DIR_TRAILER_SIGNATURE);
trailer->db_compat_rec_len = trailer->db_compat_rec_len =
cpu_to_le16(sizeof(struct ocfs2_dir_block_trailer)); cpu_to_le16(sizeof(struct ocfs2_dir_block_trailer));
trailer->db_parent_dinode = cpu_to_le64(OCFS2_I(inode)->ip_blkno); trailer->db_parent_dinode = cpu_to_le64(OCFS2_I(inode)->ip_blkno);
@ -2213,14 +2213,14 @@ static struct ocfs2_dir_entry *ocfs2_fill_initial_dirents(struct inode *inode,
de->name_len = 1; de->name_len = 1;
de->rec_len = de->rec_len =
cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len)); cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len));
strcpy(de->name, "."); strscpy(de->name, ".");
ocfs2_set_de_type(de, S_IFDIR); ocfs2_set_de_type(de, S_IFDIR);
de = (struct ocfs2_dir_entry *) ((char *)de + le16_to_cpu(de->rec_len)); de = (struct ocfs2_dir_entry *) ((char *)de + le16_to_cpu(de->rec_len));
de->inode = cpu_to_le64(OCFS2_I(parent)->ip_blkno); de->inode = cpu_to_le64(OCFS2_I(parent)->ip_blkno);
de->rec_len = cpu_to_le16(size - OCFS2_DIR_REC_LEN(1)); de->rec_len = cpu_to_le16(size - OCFS2_DIR_REC_LEN(1));
de->name_len = 2; de->name_len = 2;
strcpy(de->name, ".."); strscpy(de->name, "..");
ocfs2_set_de_type(de, S_IFDIR); ocfs2_set_de_type(de, S_IFDIR);
return de; return de;
@ -2378,7 +2378,7 @@ static int ocfs2_dx_dir_attach_index(struct ocfs2_super *osb,
dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data; dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
memset(dx_root, 0, osb->sb->s_blocksize); memset(dx_root, 0, osb->sb->s_blocksize);
strcpy(dx_root->dr_signature, OCFS2_DX_ROOT_SIGNATURE); strscpy(dx_root->dr_signature, OCFS2_DX_ROOT_SIGNATURE);
dx_root->dr_suballoc_slot = cpu_to_le16(meta_ac->ac_alloc_slot); dx_root->dr_suballoc_slot = cpu_to_le16(meta_ac->ac_alloc_slot);
dx_root->dr_suballoc_loc = cpu_to_le64(suballoc_loc); dx_root->dr_suballoc_loc = cpu_to_le64(suballoc_loc);
dx_root->dr_suballoc_bit = cpu_to_le16(dr_suballoc_bit); dx_root->dr_suballoc_bit = cpu_to_le16(dr_suballoc_bit);
@ -2454,7 +2454,7 @@ static int ocfs2_dx_dir_format_cluster(struct ocfs2_super *osb,
dx_leaf = (struct ocfs2_dx_leaf *) bh->b_data; dx_leaf = (struct ocfs2_dx_leaf *) bh->b_data;
memset(dx_leaf, 0, osb->sb->s_blocksize); memset(dx_leaf, 0, osb->sb->s_blocksize);
strcpy(dx_leaf->dl_signature, OCFS2_DX_LEAF_SIGNATURE); strscpy(dx_leaf->dl_signature, OCFS2_DX_LEAF_SIGNATURE);
dx_leaf->dl_fs_generation = cpu_to_le32(osb->fs_generation); dx_leaf->dl_fs_generation = cpu_to_le32(osb->fs_generation);
dx_leaf->dl_blkno = cpu_to_le64(bh->b_blocknr); dx_leaf->dl_blkno = cpu_to_le64(bh->b_blocknr);
dx_leaf->dl_list.de_count = dx_leaf->dl_list.de_count =

View File

@ -179,7 +179,7 @@ static int ocfs2_sync_file(struct file *file, loff_t start, loff_t end,
file->f_path.dentry->d_name.name, file->f_path.dentry->d_name.name,
(unsigned long long)datasync); (unsigned long long)datasync);
if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) if (unlikely(ocfs2_emergency_state(osb)))
return -EROFS; return -EROFS;
err = file_write_and_wait_range(file, start, end); err = file_write_and_wait_range(file, start, end);
@ -209,7 +209,7 @@ int ocfs2_should_update_atime(struct inode *inode,
struct timespec64 now; struct timespec64 now;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) if (unlikely(ocfs2_emergency_state(osb)))
return 0; return 0;
if ((inode->i_flags & S_NOATIME) || if ((inode->i_flags & S_NOATIME) ||
@ -1136,6 +1136,12 @@ int ocfs2_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
attr->ia_valid & ATTR_GID ? attr->ia_valid & ATTR_GID ?
from_kgid(&init_user_ns, attr->ia_gid) : 0); from_kgid(&init_user_ns, attr->ia_gid) : 0);
status = ocfs2_emergency_state(osb);
if (unlikely(status)) {
mlog_errno(status);
goto bail;
}
/* ensuring we don't even attempt to truncate a symlink */ /* ensuring we don't even attempt to truncate a symlink */
if (S_ISLNK(inode->i_mode)) if (S_ISLNK(inode->i_mode))
attr->ia_valid &= ~ATTR_SIZE; attr->ia_valid &= ~ATTR_SIZE;
@ -1943,7 +1949,7 @@ static int __ocfs2_change_file_space(struct file *file, struct inode *inode,
handle_t *handle; handle_t *handle;
unsigned long long max_off = inode->i_sb->s_maxbytes; unsigned long long max_off = inode->i_sb->s_maxbytes;
if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) if (unlikely(ocfs2_emergency_state(osb)))
return -EROFS; return -EROFS;
inode_lock(inode); inode_lock(inode);
@ -2707,7 +2713,7 @@ static loff_t ocfs2_remap_file_range(struct file *file_in, loff_t pos_in,
return -EINVAL; return -EINVAL;
if (!ocfs2_refcount_tree(osb)) if (!ocfs2_refcount_tree(osb))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) if (unlikely(ocfs2_emergency_state(osb)))
return -EROFS; return -EROFS;
/* Lock both files against IO */ /* Lock both files against IO */

View File

@ -1442,6 +1442,14 @@ int ocfs2_validate_inode_block(struct super_block *sb,
goto bail; goto bail;
} }
if ((!di->i_links_count && !di->i_links_count_hi) || !di->i_mode) {
mlog(ML_ERROR, "Invalid dinode #%llu: "
"Corrupt state (nlink = %u or mode = %u) detected!\n",
(unsigned long long)bh->b_blocknr,
ocfs2_read_links_count(di), le16_to_cpu(di->i_mode));
rc = -EFSCORRUPTED;
goto bail;
}
/* /*
* Errors after here are fatal. * Errors after here are fatal.
*/ */
@ -1604,8 +1612,7 @@ static int ocfs2_filecheck_repair_inode_block(struct super_block *sb,
trace_ocfs2_filecheck_repair_inode_block( trace_ocfs2_filecheck_repair_inode_block(
(unsigned long long)bh->b_blocknr); (unsigned long long)bh->b_blocknr);
if (ocfs2_is_hard_readonly(OCFS2_SB(sb)) || if (unlikely(ocfs2_emergency_state(OCFS2_SB(sb)))) {
ocfs2_is_soft_readonly(OCFS2_SB(sb))) {
mlog(ML_ERROR, mlog(ML_ERROR,
"Filecheck: cannot repair dinode #%llu " "Filecheck: cannot repair dinode #%llu "
"on readonly filesystem\n", "on readonly filesystem\n",

View File

@ -909,7 +909,7 @@ static int ocfs2_move_extents(struct ocfs2_move_extents_context *context)
struct buffer_head *di_bh = NULL; struct buffer_head *di_bh = NULL;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) if (unlikely(ocfs2_emergency_state(osb)))
return -EROFS; return -EROFS;
inode_lock(inode); inode_lock(inode);

View File

@ -23,6 +23,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h>
#include <linux/highmem.h> #include <linux/highmem.h>
#include <linux/quotaops.h> #include <linux/quotaops.h>
#include <linux/iversion.h> #include <linux/iversion.h>
@ -568,7 +569,7 @@ static int __ocfs2_mknod_locked(struct inode *dir,
ocfs2_set_links_count(fe, inode->i_nlink); ocfs2_set_links_count(fe, inode->i_nlink);
fe->i_last_eb_blk = 0; fe->i_last_eb_blk = 0;
strcpy(fe->i_signature, OCFS2_INODE_SIGNATURE); strscpy(fe->i_signature, OCFS2_INODE_SIGNATURE);
fe->i_flags |= cpu_to_le32(OCFS2_VALID_FL); fe->i_flags |= cpu_to_le32(OCFS2_VALID_FL);
ktime_get_coarse_real_ts64(&ts); ktime_get_coarse_real_ts64(&ts);
fe->i_atime = fe->i_ctime = fe->i_mtime = fe->i_atime = fe->i_ctime = fe->i_mtime =

View File

@ -680,6 +680,24 @@ static inline int ocfs2_is_soft_readonly(struct ocfs2_super *osb)
return ret; return ret;
} }
static inline int ocfs2_is_readonly(struct ocfs2_super *osb)
{
int ret;
spin_lock(&osb->osb_lock);
ret = osb->osb_flags & (OCFS2_OSB_SOFT_RO | OCFS2_OSB_HARD_RO);
spin_unlock(&osb->osb_lock);
return ret;
}
static inline int ocfs2_emergency_state(struct ocfs2_super *osb)
{
if (ocfs2_is_readonly(osb))
return -EROFS;
return 0;
}
static inline int ocfs2_clusterinfo_valid(struct ocfs2_super *osb) static inline int ocfs2_clusterinfo_valid(struct ocfs2_super *osb)
{ {
return (osb->s_feature_incompat & return (osb->s_feature_incompat &

View File

@ -276,7 +276,7 @@ int ocfs2_group_extend(struct inode * inode, int new_clusters)
u32 first_new_cluster; u32 first_new_cluster;
u64 lgd_blkno; u64 lgd_blkno;
if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) if (unlikely(ocfs2_emergency_state(osb)))
return -EROFS; return -EROFS;
if (new_clusters < 0) if (new_clusters < 0)
@ -466,7 +466,7 @@ int ocfs2_group_add(struct inode *inode, struct ocfs2_new_group_input *input)
u16 cl_bpc; u16 cl_bpc;
u64 bg_ptr; u64 bg_ptr;
if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) if (unlikely(ocfs2_emergency_state(osb)))
return -EROFS; return -EROFS;
main_bm_inode = ocfs2_get_system_file_inode(osb, main_bm_inode = ocfs2_get_system_file_inode(osb,

View File

@ -10,6 +10,7 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/kmod.h> #include <linux/kmod.h>
@ -670,7 +671,7 @@ static int __init ocfs2_stack_glue_init(void)
{ {
int ret; int ret;
strcpy(cluster_stack_name, OCFS2_STACK_PLUGIN_O2CB); strscpy(cluster_stack_name, OCFS2_STACK_PLUGIN_O2CB);
ocfs2_table_header = register_sysctl("fs/ocfs2/nm", ocfs2_nm_table); ocfs2_table_header = register_sysctl("fs/ocfs2/nm", ocfs2_nm_table);
if (!ocfs2_table_header) { if (!ocfs2_table_header) {

View File

@ -11,6 +11,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h>
#include <linux/highmem.h> #include <linux/highmem.h>
#include <cluster/masklog.h> #include <cluster/masklog.h>
@ -372,7 +373,7 @@ static int ocfs2_block_group_fill(handle_t *handle,
} }
memset(bg, 0, sb->s_blocksize); memset(bg, 0, sb->s_blocksize);
strcpy(bg->bg_signature, OCFS2_GROUP_DESC_SIGNATURE); strscpy(bg->bg_signature, OCFS2_GROUP_DESC_SIGNATURE);
bg->bg_generation = cpu_to_le32(osb->fs_generation); bg->bg_generation = cpu_to_le32(osb->fs_generation);
bg->bg_size = cpu_to_le16(ocfs2_group_bitmap_size(sb, 1, bg->bg_size = cpu_to_le16(ocfs2_group_bitmap_size(sb, 1,
osb->s_feature_incompat)); osb->s_feature_incompat));
@ -1992,6 +1993,16 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_alloc_context *ac,
} }
cl = (struct ocfs2_chain_list *) &fe->id2.i_chain; cl = (struct ocfs2_chain_list *) &fe->id2.i_chain;
if (!le16_to_cpu(cl->cl_next_free_rec) ||
le16_to_cpu(cl->cl_next_free_rec) > le16_to_cpu(cl->cl_count)) {
status = ocfs2_error(ac->ac_inode->i_sb,
"Chain allocator dinode %llu has invalid next "
"free chain record %u, but only %u total\n",
(unsigned long long)le64_to_cpu(fe->i_blkno),
le16_to_cpu(cl->cl_next_free_rec),
le16_to_cpu(cl->cl_count));
goto bail;
}
victim = ocfs2_find_victim_chain(cl); victim = ocfs2_find_victim_chain(cl);
ac->ac_chain = victim; ac->ac_chain = victim;

View File

@ -2487,7 +2487,7 @@ static int ocfs2_handle_error(struct super_block *sb)
rv = -EIO; rv = -EIO;
} else { /* default option */ } else { /* default option */
rv = -EROFS; rv = -EROFS;
if (sb_rdonly(sb) && (ocfs2_is_soft_readonly(osb) || ocfs2_is_hard_readonly(osb))) if (sb_rdonly(sb) && ocfs2_emergency_state(osb))
return rv; return rv;
pr_crit("OCFS2: File system is now read-only.\n"); pr_crit("OCFS2: File system is now read-only.\n");

View File

@ -49,9 +49,13 @@
#include "ocfs2_trace.h" #include "ocfs2_trace.h"
struct ocfs2_xattr_def_value_root { struct ocfs2_xattr_def_value_root {
struct ocfs2_xattr_value_root xv; /* Must be last as it ends in a flexible-array member. */
struct ocfs2_extent_rec er; TRAILING_OVERLAP(struct ocfs2_xattr_value_root, xv, xr_list.l_recs,
struct ocfs2_extent_rec er;
);
}; };
static_assert(offsetof(struct ocfs2_xattr_def_value_root, xv.xr_list.l_recs) ==
offsetof(struct ocfs2_xattr_def_value_root, er));
struct ocfs2_xattr_bucket { struct ocfs2_xattr_bucket {
/* The inode these xattrs are associated with */ /* The inode these xattrs are associated with */
@ -971,13 +975,39 @@ static int ocfs2_xattr_ibody_list(struct inode *inode,
struct ocfs2_xattr_header *header = NULL; struct ocfs2_xattr_header *header = NULL;
struct ocfs2_inode_info *oi = OCFS2_I(inode); struct ocfs2_inode_info *oi = OCFS2_I(inode);
int ret = 0; int ret = 0;
u16 xattr_count;
size_t max_entries;
u16 inline_size;
if (!(oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL)) if (!(oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL))
return ret; return ret;
inline_size = le16_to_cpu(di->i_xattr_inline_size);
/* Validate inline size is reasonable */
if (inline_size > inode->i_sb->s_blocksize ||
inline_size < sizeof(struct ocfs2_xattr_header)) {
ocfs2_error(inode->i_sb,
"Invalid xattr inline size %u in inode %llu\n",
inline_size,
(unsigned long long)OCFS2_I(inode)->ip_blkno);
return -EFSCORRUPTED;
}
header = (struct ocfs2_xattr_header *) header = (struct ocfs2_xattr_header *)
((void *)di + inode->i_sb->s_blocksize - ((void *)di + inode->i_sb->s_blocksize - inline_size);
le16_to_cpu(di->i_xattr_inline_size));
xattr_count = le16_to_cpu(header->xh_count);
max_entries = (inline_size - sizeof(struct ocfs2_xattr_header)) /
sizeof(struct ocfs2_xattr_entry);
if (xattr_count > max_entries) {
ocfs2_error(inode->i_sb,
"xattr entry count %u exceeds maximum %zu in inode %llu\n",
xattr_count, max_entries,
(unsigned long long)OCFS2_I(inode)->ip_blkno);
return -EFSCORRUPTED;
}
ret = ocfs2_xattr_list_entries(inode, header, buffer, buffer_size); ret = ocfs2_xattr_list_entries(inode, header, buffer, buffer_size);

View File

@ -6,9 +6,9 @@
/* /*
* How do these macros work? * How do these macros work?
* *
* In __COUNT_ARGS() _0 to _12 are just placeholders from the start * In __COUNT_ARGS() _0 to _15 are just placeholders from the start
* in order to make sure _n is positioned over the correct number * in order to make sure _n is positioned over the correct number
* from 12 to 0 (depending on X, which is a variadic argument list). * from 15 to 0 (depending on X, which is a variadic argument list).
* They serve no purpose other than occupying a position. Since each * They serve no purpose other than occupying a position. Since each
* macro parameter must have a distinct identifier, those identifiers * macro parameter must have a distinct identifier, those identifiers
* are as good as any. * are as good as any.

View File

@ -54,6 +54,7 @@ config KEXEC_HANDOVER_ENABLE_DEFAULT
config LIVEUPDATE config LIVEUPDATE
bool "Live Update Orchestrator" bool "Live Update Orchestrator"
depends on KEXEC_HANDOVER depends on KEXEC_HANDOVER
depends on SHMEM
help help
Enable the Live Update Orchestrator. Live Update is a mechanism, Enable the Live Update Orchestrator. Live Update is a mechanism,
typically based on kexec, that allows the kernel to be updated typically based on kexec, that allows the kernel to be updated

View File

@ -399,10 +399,8 @@ static long luo_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
int err; int err;
nr = _IOC_NR(cmd); nr = _IOC_NR(cmd);
if (nr < LIVEUPDATE_CMD_BASE || if (nr - LIVEUPDATE_CMD_BASE >= ARRAY_SIZE(luo_ioctl_ops))
(nr - LIVEUPDATE_CMD_BASE) >= ARRAY_SIZE(luo_ioctl_ops)) {
return -EINVAL; return -EINVAL;
}
ucmd.ubuffer = (void __user *)arg; ucmd.ubuffer = (void __user *)arg;
err = get_user(ucmd.user_size, (u32 __user *)ucmd.ubuffer); err = get_user(ucmd.user_size, (u32 __user *)ucmd.ubuffer);

View File

@ -554,17 +554,20 @@ int luo_retrieve_file(struct luo_file_set *file_set, u64 token,
{ {
struct liveupdate_file_op_args args = {0}; struct liveupdate_file_op_args args = {0};
struct luo_file *luo_file; struct luo_file *luo_file;
bool found = false;
int err; int err;
if (list_empty(&file_set->files_list)) if (list_empty(&file_set->files_list))
return -ENOENT; return -ENOENT;
list_for_each_entry(luo_file, &file_set->files_list, list) { list_for_each_entry(luo_file, &file_set->files_list, list) {
if (luo_file->token == token) if (luo_file->token == token) {
found = true;
break; break;
}
} }
if (luo_file->token != token) if (!found)
return -ENOENT; return -ENOENT;
guard(mutex)(&luo_file->mutex); guard(mutex)(&luo_file->mutex);

View File

@ -5794,8 +5794,15 @@ EXPORT_SYMBOL_GPL(shmem_truncate_range);
#define shmem_vm_ops generic_file_vm_ops #define shmem_vm_ops generic_file_vm_ops
#define shmem_anon_vm_ops generic_file_vm_ops #define shmem_anon_vm_ops generic_file_vm_ops
#define shmem_file_operations ramfs_file_operations #define shmem_file_operations ramfs_file_operations
#define shmem_acct_size(flags, size) 0
#define shmem_unacct_size(flags, size) do {} while (0) static inline int shmem_acct_size(unsigned long flags, loff_t size)
{
return 0;
}
static inline void shmem_unacct_size(unsigned long flags, loff_t size)
{
}
static inline struct inode *shmem_get_inode(struct mnt_idmap *idmap, static inline struct inode *shmem_get_inode(struct mnt_idmap *idmap,
struct super_block *sb, struct inode *dir, struct super_block *sb, struct inode *dir,

View File

@ -7732,6 +7732,12 @@ sub process {
ERROR("MISSING_SENTINEL", "missing sentinel in ID array\n" . "$here\n$stat\n"); ERROR("MISSING_SENTINEL", "missing sentinel in ID array\n" . "$here\n$stat\n");
} }
} }
# check for uninitialized pointers with __free attribute
while ($line =~ /\*\s*($Ident)\s+__free\s*\(\s*$Ident\s*\)\s*[,;]/g) {
ERROR("UNINITIALIZED_PTR_WITH_FREE",
"pointer '$1' with __free attribute should be initialized\n" . $herecurr);
}
} }
# If we have no input at all, then there is nothing to report on # If we have no input at all, then there is nothing to report on