From: Pavel Begunkov <asml.silence@gmail.com>
To: Stefan Metzmacher <metze@samba.org>, Jens Axboe <axboe@kernel.dk>
Cc: io-uring <io-uring@vger.kernel.org>,
Linux API Mailing List <linux-api@vger.kernel.org>
Subject: Re: IORING_REGISTER_CREDS[_UPDATE]() and credfd_create()?
Date: Wed, 29 Jan 2020 17:23:25 +0300 [thread overview]
Message-ID: <3e1289de-8d8e-49cf-cc9f-fb7bc67f35d5@gmail.com> (raw)
In-Reply-To: <40d52623-5f9c-d804-cdeb-b7da6b13cb4f@samba.org>
On 1/29/2020 4:56 PM, Stefan Metzmacher wrote:
>>> However I think there're a few things to improve/simplify.
>> Since 5.6 is already semi-open, it'd be great to have an incremental
>> patch for that. I'll retoss things as usual, if nobody do it before.
>
> I'll wait for comments from Jens first:-)
> I guess we'll have things changed in his branch, when I wake up
> tomorrow. Otherwise I can also create patches and submit them.
Sure, I won't get there any time soon.
>
> But I currently don't have an environment where I can do runtime tests
> with it.
>
>>>> https://git.kernel.dk/cgit/linux-block/commit/?h=for-5.6/io_uring-vfs&id=a26d26412e1e1783473f9dc8f030c3af3d54b1a6
>>>
>>> In fs/io_uring.c mmgrab() and get_current_cred() are used together in
>>> two places, why is put_cred() called in __io_req_aux_free while
>>> mmdrop() is called from io_put_work(). I think both should be called
>>> in io_put_work(), that makes the code much easier to understand.
>>>
>>> My guess is that you choose __io_req_aux_free() for put_cred() because
>>> of the following patches, but I'll explain on the other commit
>>> why it's not needed.
>>>
>>>> https://git.kernel.dk/cgit/linux-block/commit/?h=for-5.6/io_uring-vfs&id=d9db233adf034bd7855ba06190525e10a05868be
>>>
>>> A minor one would be starting with 1 instead of 0 and using
>>> idr_alloc_cyclic() in order to avoid immediate reuse of ids.
>>> That way we could include the id in the tracing message and
>>> 0 would mean the current creds were used.
>>>
>>>> +static int io_remove_personalities(int id, void *p, void *data)
>>>> +{
>>>> + struct io_ring_ctx *ctx = data;
>>>> +
>>>> + idr_remove(&ctx->personality_idr, id);
>>>
>>> Here we need something like:
>>> put_creds((const struct cred *)p);
>>
>> Good catch
>>
>>>
>>>> + return 0;
>>>> +}
>>>
>>>
>>> The io_uring_register() calles would look like this, correct?
>>>
>>> id = io_uring_register(ring_fd, IORING_REGISTER_PERSONALITY, NULL, 0);
>>> io_uring_register(ring_fd, IORING_UNREGISTER_PERSONALITY, NULL, id);
>>>
>>>> https://git.kernel.dk/cgit/linux-block/commit/?h=for-5.6/io_uring-vfs&id=eec9e69e0ad9ad364e1b6a5dfc52ad576afee235
>>>> +
>>>> + if (sqe_flags & IOSQE_PERSONALITY) {
>>>> + int id = READ_ONCE(sqe->personality);
>>>> +
>>>> + req->work.creds = idr_find(&ctx->personality_idr, id);
>>>> + if (unlikely(!req->work.creds)) {
>>>> + ret = -EINVAL;
>>>> + goto err_req;
>>>> + }
>>>> + get_cred(req->work.creds);> + old_creds = override_creds(req->work.creds);
>>>> + }
>>>> +
>>>
>>> Here we could use a helper variable
>>> const struct cred *personality_creds;
>>> and leave req->work.creds as NULL.
>>> It means we can avoid the explicit get_cred() call
>>> and can skip the following hunk too:
>>>
>>>> @@ -3977,7 +3977,8 @@ static int io_req_defer_prep(struct io_kiocb *req,
>>>> mmgrab(current->mm);
>>>> req->work.mm = current->mm;
>>>> }
>>>> - req->work.creds = get_current_cred();
>>>> + if (!req->work.creds)
>>>> + req->work.creds = get_current_cred();
>>>>
>>>> switch (req->opcode) {
>>>> case IORING_OP_NOP:
>>>
>>> The override_creds(personality_creds) has changed current->cred
>>> and get_current_cred() will just pick it up as in the default case.
>>>
>>> This would make the patch much simpler and allows put_cred() to be
>>> in io_put_work() instead of __io_req_aux_free() as explained above.
>>>
>>
>> It's one extra get_current_cred(). I'd prefer to find another way to
>> clean this up.
>
> As far as I can see it avoids a get_cred() in the IOSQE_PERSONALITY case
> and the if (!req->work.creds) for both cases.
Great, that you turned attention to that! override_creds() is already
grabbing a ref, so it shouldn't call get_cred() there.
So, that's a bug.
It could be I'm wrong with the statement above, need to recheck all this
code to be sure.
BTW, io_req_defer_prep() may be called twice for a req, so you will
reassign it without putting a ref. It's safer to leave NULL checks. At
least, until I've done reworking and fixing preparation paths.
>
> What do you mean exactly with one extra get_current_cred()?
> Is that any worse than calling get_cred() and having an if check?
>
> It also seems to avoid req->work.creds from being filled at all
> for the non-blocking case.
>
> metze
>
--
Pavel Begunkov
WARNING: multiple messages have this Message-ID (diff)
From: Pavel Begunkov <asml.silence-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
To: Stefan Metzmacher <metze-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>,
Jens Axboe <axboe-tSWWG44O7X1aa/9Udqfwiw@public.gmane.org>
Cc: io-uring <io-uring-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
Linux API Mailing List
<linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
Subject: Re: IORING_REGISTER_CREDS[_UPDATE]() and credfd_create()?
Date: Wed, 29 Jan 2020 17:23:25 +0300 [thread overview]
Message-ID: <3e1289de-8d8e-49cf-cc9f-fb7bc67f35d5@gmail.com> (raw)
In-Reply-To: <40d52623-5f9c-d804-cdeb-b7da6b13cb4f-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
On 1/29/2020 4:56 PM, Stefan Metzmacher wrote:
>>> However I think there're a few things to improve/simplify.
>> Since 5.6 is already semi-open, it'd be great to have an incremental
>> patch for that. I'll retoss things as usual, if nobody do it before.
>
> I'll wait for comments from Jens first:-)
> I guess we'll have things changed in his branch, when I wake up
> tomorrow. Otherwise I can also create patches and submit them.
Sure, I won't get there any time soon.
>
> But I currently don't have an environment where I can do runtime tests
> with it.
>
>>>> https://git.kernel.dk/cgit/linux-block/commit/?h=for-5.6/io_uring-vfs&id=a26d26412e1e1783473f9dc8f030c3af3d54b1a6
>>>
>>> In fs/io_uring.c mmgrab() and get_current_cred() are used together in
>>> two places, why is put_cred() called in __io_req_aux_free while
>>> mmdrop() is called from io_put_work(). I think both should be called
>>> in io_put_work(), that makes the code much easier to understand.
>>>
>>> My guess is that you choose __io_req_aux_free() for put_cred() because
>>> of the following patches, but I'll explain on the other commit
>>> why it's not needed.
>>>
>>>> https://git.kernel.dk/cgit/linux-block/commit/?h=for-5.6/io_uring-vfs&id=d9db233adf034bd7855ba06190525e10a05868be
>>>
>>> A minor one would be starting with 1 instead of 0 and using
>>> idr_alloc_cyclic() in order to avoid immediate reuse of ids.
>>> That way we could include the id in the tracing message and
>>> 0 would mean the current creds were used.
>>>
>>>> +static int io_remove_personalities(int id, void *p, void *data)
>>>> +{
>>>> + struct io_ring_ctx *ctx = data;
>>>> +
>>>> + idr_remove(&ctx->personality_idr, id);
>>>
>>> Here we need something like:
>>> put_creds((const struct cred *)p);
>>
>> Good catch
>>
>>>
>>>> + return 0;
>>>> +}
>>>
>>>
>>> The io_uring_register() calles would look like this, correct?
>>>
>>> id = io_uring_register(ring_fd, IORING_REGISTER_PERSONALITY, NULL, 0);
>>> io_uring_register(ring_fd, IORING_UNREGISTER_PERSONALITY, NULL, id);
>>>
>>>> https://git.kernel.dk/cgit/linux-block/commit/?h=for-5.6/io_uring-vfs&id=eec9e69e0ad9ad364e1b6a5dfc52ad576afee235
>>>> +
>>>> + if (sqe_flags & IOSQE_PERSONALITY) {
>>>> + int id = READ_ONCE(sqe->personality);
>>>> +
>>>> + req->work.creds = idr_find(&ctx->personality_idr, id);
>>>> + if (unlikely(!req->work.creds)) {
>>>> + ret = -EINVAL;
>>>> + goto err_req;
>>>> + }
>>>> + get_cred(req->work.creds);> + old_creds = override_creds(req->work.creds);
>>>> + }
>>>> +
>>>
>>> Here we could use a helper variable
>>> const struct cred *personality_creds;
>>> and leave req->work.creds as NULL.
>>> It means we can avoid the explicit get_cred() call
>>> and can skip the following hunk too:
>>>
>>>> @@ -3977,7 +3977,8 @@ static int io_req_defer_prep(struct io_kiocb *req,
>>>> mmgrab(current->mm);
>>>> req->work.mm = current->mm;
>>>> }
>>>> - req->work.creds = get_current_cred();
>>>> + if (!req->work.creds)
>>>> + req->work.creds = get_current_cred();
>>>>
>>>> switch (req->opcode) {
>>>> case IORING_OP_NOP:
>>>
>>> The override_creds(personality_creds) has changed current->cred
>>> and get_current_cred() will just pick it up as in the default case.
>>>
>>> This would make the patch much simpler and allows put_cred() to be
>>> in io_put_work() instead of __io_req_aux_free() as explained above.
>>>
>>
>> It's one extra get_current_cred(). I'd prefer to find another way to
>> clean this up.
>
> As far as I can see it avoids a get_cred() in the IOSQE_PERSONALITY case
> and the if (!req->work.creds) for both cases.
Great, that you turned attention to that! override_creds() is already
grabbing a ref, so it shouldn't call get_cred() there.
So, that's a bug.
It could be I'm wrong with the statement above, need to recheck all this
code to be sure.
BTW, io_req_defer_prep() may be called twice for a req, so you will
reassign it without putting a ref. It's safer to leave NULL checks. At
least, until I've done reworking and fixing preparation paths.
>
> What do you mean exactly with one extra get_current_cred()?
> Is that any worse than calling get_cred() and having an if check?
>
> It also seems to avoid req->work.creds from being filled at all
> for the non-blocking case.
>
> metze
>
--
Pavel Begunkov
next prev parent reply other threads:[~2020-01-29 14:23 UTC|newest]
Thread overview: 96+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-01-28 10:18 IORING_REGISTER_CREDS[_UPDATE]() and credfd_create()? Stefan Metzmacher
2020-01-28 10:18 ` Stefan Metzmacher
2020-01-28 16:10 ` Jens Axboe
2020-01-28 16:10 ` Jens Axboe
2020-01-28 16:17 ` Stefan Metzmacher
2020-01-28 16:17 ` Stefan Metzmacher
2020-01-28 16:19 ` Jens Axboe
2020-01-28 16:19 ` Jens Axboe
2020-01-28 17:19 ` Jens Axboe
2020-01-28 17:19 ` Jens Axboe
2020-01-28 18:04 ` Jens Axboe
2020-01-28 18:04 ` Jens Axboe
2020-01-28 19:42 ` Jens Axboe
2020-01-28 19:42 ` Jens Axboe
2020-01-28 20:16 ` Pavel Begunkov
2020-01-28 20:16 ` Pavel Begunkov
2020-01-28 20:19 ` Jens Axboe
2020-01-28 20:19 ` Jens Axboe
2020-01-28 20:50 ` Pavel Begunkov
2020-01-28 20:50 ` Pavel Begunkov
2020-01-28 20:56 ` Jens Axboe
2020-01-28 20:56 ` Jens Axboe
2020-01-28 21:25 ` Christian Brauner
2020-01-28 21:25 ` Christian Brauner
2020-01-28 22:38 ` Pavel Begunkov
2020-01-28 22:38 ` Pavel Begunkov
2020-01-28 23:36 ` Pavel Begunkov
2020-01-28 23:36 ` Pavel Begunkov
2020-01-28 23:40 ` Jens Axboe
2020-01-28 23:40 ` Jens Axboe
2020-01-28 23:51 ` Jens Axboe
2020-01-28 23:51 ` Jens Axboe
2020-01-29 0:10 ` Pavel Begunkov
2020-01-29 0:10 ` Pavel Begunkov
2020-01-29 0:15 ` Jens Axboe
2020-01-29 0:15 ` Jens Axboe
2020-01-29 0:18 ` Jens Axboe
2020-01-29 0:18 ` Jens Axboe
2020-01-29 0:20 ` Jens Axboe
2020-01-29 0:20 ` Jens Axboe
2020-01-29 0:21 ` Pavel Begunkov
2020-01-29 0:21 ` Pavel Begunkov
2020-01-29 0:24 ` Jens Axboe
2020-01-29 0:24 ` Jens Axboe
2020-01-29 0:54 ` Jens Axboe
2020-01-29 0:54 ` Jens Axboe
2020-01-29 10:17 ` Pavel Begunkov
2020-01-29 10:17 ` Pavel Begunkov
2020-01-29 13:11 ` Stefan Metzmacher
2020-01-29 13:11 ` Stefan Metzmacher
2020-01-29 13:41 ` Pavel Begunkov
2020-01-29 13:41 ` Pavel Begunkov
2020-01-29 13:56 ` Stefan Metzmacher
2020-01-29 13:56 ` Stefan Metzmacher
2020-01-29 14:23 ` Pavel Begunkov [this message]
2020-01-29 14:23 ` Pavel Begunkov
2020-01-29 14:27 ` Stefan Metzmacher
2020-01-29 14:27 ` Stefan Metzmacher
2020-01-29 14:34 ` Pavel Begunkov
2020-01-29 14:34 ` Pavel Begunkov
2020-01-29 17:34 ` Jens Axboe
2020-01-29 17:34 ` Jens Axboe
2020-01-29 17:42 ` Jens Axboe
2020-01-29 17:42 ` Jens Axboe
2020-01-29 20:09 ` Stefan Metzmacher
2020-01-29 20:09 ` Stefan Metzmacher
2020-01-29 20:48 ` Jens Axboe
2020-01-29 20:48 ` Jens Axboe
2020-01-29 17:46 ` Pavel Begunkov
2020-01-29 17:46 ` Pavel Begunkov
2020-01-29 14:59 ` Jann Horn
2020-01-29 14:59 ` Jann Horn
2020-01-29 17:34 ` Jens Axboe
2020-01-29 17:34 ` Jens Axboe
2020-01-30 1:08 ` Jens Axboe
2020-01-30 1:08 ` Jens Axboe
2020-01-30 2:20 ` Jens Axboe
2020-01-30 2:20 ` Jens Axboe
2020-01-30 3:18 ` Jens Axboe
2020-01-30 3:18 ` Jens Axboe
2020-01-30 6:53 ` Stefan Metzmacher
2020-01-30 6:53 ` Stefan Metzmacher
2020-01-30 10:11 ` Jann Horn
2020-01-30 10:11 ` Jann Horn
2020-01-30 10:26 ` Christian Brauner
2020-01-30 10:26 ` Christian Brauner
2020-01-30 14:11 ` Jens Axboe
2020-01-30 14:11 ` Jens Axboe
2020-01-30 14:47 ` Stefan Metzmacher
2020-01-30 14:47 ` Stefan Metzmacher
2020-01-30 15:34 ` Jens Axboe
2020-01-30 15:34 ` Jens Axboe
2020-01-30 15:13 ` Christian Brauner
2020-01-30 15:13 ` Christian Brauner
2020-01-30 15:29 ` Jens Axboe
2020-01-30 15:29 ` Jens Axboe
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=3e1289de-8d8e-49cf-cc9f-fb7bc67f35d5@gmail.com \
--to=asml.silence@gmail.com \
--cc=axboe@kernel.dk \
--cc=io-uring@vger.kernel.org \
--cc=linux-api@vger.kernel.org \
--cc=metze@samba.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.