mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Jens Axboe <axboe@kernel.dk>
To: harshal24-chavan <harshal24.chavan@gmail.com>, kees@kernel.org
Cc: gustavoars@kernel.org, io-uring@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-hardening@vger.kernel.org
Subject: Re: [PATCH v2] [PATCH v2] io_uring/register: add IORING_REGISTER_CLONE_FILES opcode
Date: Wed, 17 Jun 2026 08:54:04 -0600	[thread overview]
Message-ID: <2d35e4d2-72ec-4ae8-90ba-8c9b1e53c58f@kernel.dk> (raw)
In-Reply-To: <20260617081622.32823-1-harshal24.chavan@gmail.com>

On 6/17/26 2:16 AM, harshal24-chavan wrote:
> diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
> index 650303626be6..1e4e114ca5a5 100644
> --- a/io_uring/rsrc.c
> +++ b/io_uring/rsrc.c
> @@ -1303,6 +1303,166 @@ int io_register_clone_buffers(struct io_ring_ctx *ctx, void __user *arg)
>  	return ret;
>  }
>  
> +
> +static int io_clone_files(struct io_ring_ctx *ctx, struct io_ring_ctx *src_ctx,
> +			  struct io_uring_clone_files *arg)
> +{
> +	struct io_file_table new_file_table;
> +	int i, off, nr;
> +	unsigned int src_nr;
> +
> +	lockdep_assert_held(&ctx->uring_lock);
> +	lockdep_assert_held(&src_ctx->uring_lock);
> +
> +	/* if offsets are given, must have nr specified too */
> +	if (!arg->nr && (arg->dst_off || arg->src_off))
> +		return -EINVAL;

Not sure the offsets and partial copies are going to be worth it, but
I'm willing to have my mind changed. But that's a minor thing really.

> +	/* not allowed unless REPLACE is set */
> +	if (ctx->file_table.data.nr &&
> +	    !(arg->flags & IORING_REGISTER_DST_REPLACE))
> +		return -EBUSY;
> +
> +	src_nr = src_ctx->file_table.data.nr;
> +	if (!src_nr)
> +		return -ENXIO;
> +	if (!arg->nr)
> +		arg->nr = src_nr;
> +	else if (arg->nr > src_nr)
> +		return -EINVAL;
> +	else if (arg->nr > IORING_MAX_FIXED_FILES)
> +		return -EINVAL;
> +	if (check_add_overflow(arg->nr, arg->src_off, &off) || off > src_nr)
> +		return -EOVERFLOW;
> +	if (check_add_overflow(arg->nr, arg->dst_off, &src_nr))
> +		return -EOVERFLOW;
> +	if (src_nr > IORING_MAX_FIXED_FILES)
> +		return -EINVAL;
> +	/* Allocate file tables memory {data + bitmap} into new_file_table */
> +	memset(&new_file_table, 0, sizeof(new_file_table));
> +	if (!io_alloc_file_tables(ctx, &new_file_table,
> +				  max(src_nr, ctx->file_table.data.nr)))
> +		return -ENOMEM;

Also a question whether the destination should've already allocated a
sparse table. This kind of bundles the two into one. In general, as
mention on the GH link, I do think this should work exactly like cloning
buffers. It'd be somewhat confusing if they don't match up, as it's
essentially the same operation, just on a different node type.


> +	/* Copy original dst nodes from before the cloned range */
> +	for (i = 0; i < min(arg->dst_off, ctx->file_table.data.nr); i++) {
> +		struct io_rsrc_node *node = ctx->file_table.data.nodes[i];
> +
> +		if (node) {
> +			new_file_table.data.nodes[i] = node;
> +			node->refs++;
> +			io_file_bitmap_set(&new_file_table, i);
> +		}
> +	}

This definitely won't work - I also mentioned in the GH link that nodes
cannot be shared, you have to allocate new nodes on the destination
side.

> +	while (nr--) {
> +		struct io_rsrc_node *dst_node, *src_node;
> +
> +		src_node = io_rsrc_node_lookup(&src_ctx->file_table.data, i);
> +		if (!src_node) {
> +			dst_node = NULL;
> +		} else {
> +			dst_node = io_rsrc_node_alloc(ctx, IORING_RSRC_FILE);
> +			if (!dst_node) {
> +				io_free_file_tables(ctx, &new_file_table);
> +				return -ENOMEM;
> +			}
> +
> +			struct file *file = io_slot_file(src_node);
> +
> +			get_file(file);
> +			io_fixed_file_set(dst_node, file);
> +		}
> +		new_file_table.data.nodes[off] = dst_node;
> +		if (dst_node)
> +			io_file_bitmap_set(&new_file_table, off);
> +
> +		i++;
> +		off++;
> +	}

Same here, it needs a new node that's private to the destination. Hence
you'd need to _always_ allocate one, assign the file, and get a
reference to it.

The file nodes rely on non-atomic refs when being used, which is
protected by the ctx->uring_lock as that's always held for the fast path
issue. If you just assign the node by reference, now you have two
different rings manipulating the same node in memory, but they don't
agree on synchronization.

-- 
Jens Axboe

  reply	other threads:[~2026-06-17 14:54 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-17  8:16 harshal24-chavan
2026-06-17 14:54 ` Jens Axboe [this message]
2026-06-19  7:32   ` Harshal Chavan
2026-06-17 22:33 ` Gabriel Krisman Bertazi
2026-06-19  7:40   ` harshal24-chavan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2d35e4d2-72ec-4ae8-90ba-8c9b1e53c58f@kernel.dk \
    --to=axboe@kernel.dk \
    --cc=gustavoars@kernel.org \
    --cc=harshal24.chavan@gmail.com \
    --cc=io-uring@vger.kernel.org \
    --cc=kees@kernel.org \
    --cc=linux-hardening@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox