Merge tag 'for-linus-7.1-ofs1' of git://git.kernel.org/pub/scm/linux/kernel/git/hubcap/linux

Pull orangefs updates from Mike Marshall:
 "Fixes:
   - validate getxattr response length
   - don't overflow the bufmap slot on readahead
   - fix parsing problem with kernel debug keywords

  Cleanup:
   - take better advantage of strscpy

  New:
   - manage bufmap as folios
   - add usercopy whitelist to orangefs_op_cache"

* tag 'for-linus-7.1-ofs1' of git://git.kernel.org/pub/scm/linux/kernel/git/hubcap/linux:
  bufmap: manage as folios, V2.
  orangefs: validate getxattr response length
  orangefs_readahead: don't overflow the bufmap slot.
  debugfs: take better advantage of strscpy.
  orangefs: add usercopy whitelist to orangefs_op_cache
  orangefs-debugfs.c: fix parsing problem with kernel debug keywords.
This commit is contained in:
Linus Torvalds
2026-04-17 17:03:43 -07:00
5 changed files with 412 additions and 74 deletions
+27 -9
View File
@@ -224,6 +224,8 @@ static void orangefs_readahead(struct readahead_control *rac)
loff_t new_start = readahead_pos(rac);
int ret;
size_t new_len = 0;
size_t this_size;
size_t remaining;
loff_t bytes_remaining = inode->i_size - readahead_pos(rac);
loff_t pages_remaining = bytes_remaining / PAGE_SIZE;
@@ -239,17 +241,33 @@ static void orangefs_readahead(struct readahead_control *rac)
offset = readahead_pos(rac);
i_pages = &rac->mapping->i_pages;
iov_iter_xarray(&iter, ITER_DEST, i_pages, offset, readahead_length(rac));
iov_iter_xarray(&iter, ITER_DEST, i_pages,
offset, readahead_length(rac));
/* read in the pages. */
if ((ret = wait_for_direct_io(ORANGEFS_IO_READ, inode,
&offset, &iter, readahead_length(rac),
inode->i_size, NULL, NULL, rac->file)) < 0)
gossip_debug(GOSSIP_FILE_DEBUG,
"%s: wait_for_direct_io failed. \n", __func__);
else
ret = 0;
remaining = readahead_length(rac);
while (remaining) {
if (remaining > 4194304)
this_size = 4194304;
else
this_size = remaining;
/* read in the pages. */
if ((ret = wait_for_direct_io(ORANGEFS_IO_READ, inode,
&offset, &iter, this_size,
inode->i_size, NULL, NULL, rac->file)) < 0) {
gossip_debug(GOSSIP_FILE_DEBUG,
"%s: wait_for_direct_io failed. :%d: \n",
__func__, ret);
goto cleanup;
} else {
ret = 0;
}
remaining -= this_size;
offset += this_size;
}
cleanup:
/* clean up. */
while ((folio = readahead_folio(rac))) {
if (!ret)
File diff suppressed because it is too large Load Diff
+5 -1
View File
@@ -19,10 +19,14 @@ static struct kmem_cache *op_cache;
int op_cache_initialize(void)
{
op_cache = kmem_cache_create("orangefs_op_cache",
op_cache = kmem_cache_create_usercopy("orangefs_op_cache",
sizeof(struct orangefs_kernel_op_s),
0,
0,
offsetof(struct orangefs_kernel_op_s, tag),
offsetof(struct orangefs_kernel_op_s, upcall) +
sizeof(struct orangefs_upcall_s) -
offsetof(struct orangefs_kernel_op_s, tag),
NULL);
if (!op_cache) {
+17 -20
View File
@@ -238,12 +238,10 @@ void orangefs_debugfs_init(int debug_mask)
static void orangefs_kernel_debug_init(void)
{
static char k_buffer[ORANGEFS_MAX_DEBUG_STRING_LEN] = { };
size_t len = strlen(kernel_debug_string);
size_t len =
strscpy(k_buffer, kernel_debug_string, sizeof(k_buffer) - 1);
gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__);
if (len + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) {
memcpy(k_buffer, kernel_debug_string, len);
if (len > 0) {
k_buffer[len] = '\n';
k_buffer[len + 1] = '\0';
} else {
@@ -339,12 +337,10 @@ static int help_show(struct seq_file *m, void *v)
static void orangefs_client_debug_init(void)
{
static char c_buffer[ORANGEFS_MAX_DEBUG_STRING_LEN] = { };
size_t len = strlen(client_debug_string);
size_t len =
strscpy(c_buffer, client_debug_string, sizeof(c_buffer) - 1);
gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__);
if (len + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) {
memcpy(c_buffer, client_debug_string, len);
if (len > 0) {
c_buffer[len] = '\n';
c_buffer[len + 1] = '\0';
} else {
@@ -443,7 +439,7 @@ static ssize_t orangefs_debug_write(struct file *file,
count = ORANGEFS_MAX_DEBUG_STRING_LEN;
}
buf = memdup_user_nul(ubuf, count - 1);
buf = memdup_user_nul(ubuf, count);
if (IS_ERR(buf)) {
gossip_debug(GOSSIP_DEBUGFS_DEBUG,
"%s: memdup_user_nul failed!\n",
@@ -452,6 +448,7 @@ static ssize_t orangefs_debug_write(struct file *file,
buf = NULL;
goto out;
}
strim(buf);
/*
* Map the keyword string from userspace into a valid debug mask.
@@ -873,9 +870,10 @@ out:
*/
static void debug_string_to_mask(char *debug_string, void *mask, int type)
{
char *unchecked_keyword;
int i;
char *strsep_fodder = kstrdup(debug_string, GFP_KERNEL);
char *trimmed;
char *token;
char *original_pointer;
int element_count = 0;
struct client_debug_mask *c_mask = NULL;
@@ -893,18 +891,17 @@ static void debug_string_to_mask(char *debug_string, void *mask, int type)
}
original_pointer = strsep_fodder;
while ((unchecked_keyword = strsep(&strsep_fodder, ",")))
if (strlen(unchecked_keyword)) {
while ((token = strsep(&strsep_fodder, ",")) != NULL) {
trimmed = strim(token);
if (*trimmed) {
for (i = 0; i < element_count; i++)
if (type)
do_c_mask(i,
unchecked_keyword,
&c_mask);
do_c_mask(i, trimmed, &c_mask);
else
do_k_mask(i,
unchecked_keyword,
&k_mask);
do_k_mask(i, trimmed, &k_mask);
}
}
kfree(original_pointer);
}
+4
View File
@@ -188,6 +188,10 @@ ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name,
* Length returned includes null terminator.
*/
length = new_op->downcall.resp.getxattr.val_sz;
if (length < 0 || length > ORANGEFS_MAX_XATTR_VALUELEN) {
ret = -EIO;
goto out_release_op;
}
/*
* Just return the length of the queried attribute.