Bug 239513 - [macOS] The function getpwnam can sometimes fail
Summary: [macOS] The function getpwnam can sometimes fail
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebKit Misc. (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords: InRadar
: 237017 (view as bug list)
Depends on:
Blocks:
 
Reported: 2022-04-19 12:05 PDT by Per Arne Vollan
Modified: 2022-06-23 15:31 PDT (History)
10 users (show)

See Also:


Attachments
Patch (31.10 KB, patch)
2022-04-19 12:09 PDT, Per Arne Vollan
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (10.56 KB, patch)
2022-04-19 16:55 PDT, Per Arne Vollan
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (10.65 KB, patch)
2022-04-19 17:29 PDT, Per Arne Vollan
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (11.24 KB, patch)
2022-04-22 13:23 PDT, Per Arne Vollan
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (11.30 KB, patch)
2022-04-25 08:11 PDT, Per Arne Vollan
no flags Details | Formatted Diff | Diff
Patch (11.65 KB, patch)
2022-04-25 09:11 PDT, Per Arne Vollan
darin: review+
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (13.51 KB, patch)
2022-04-26 09:04 PDT, Per Arne Vollan
no flags Details | Formatted Diff | Diff
Patch (13.52 KB, patch)
2022-04-26 09:07 PDT, Per Arne Vollan
no flags Details | Formatted Diff | Diff
Patch (13.73 KB, patch)
2022-04-26 10:57 PDT, Per Arne Vollan
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Per Arne Vollan 2022-04-19 12:05:58 PDT
The function getpwnam can sometimes fail in the WebContent and GPU process, since the in-process cache for the result of getpwnam can be evicted, and the sandbox is blocking access to the Open Directory daemon.
Comment 1 Per Arne Vollan 2022-04-19 12:09:01 PDT
Created attachment 457925 [details]
Patch
Comment 2 Per Arne Vollan 2022-04-19 16:55:05 PDT
Created attachment 457944 [details]
Patch
Comment 3 Per Arne Vollan 2022-04-19 17:29:11 PDT
Created attachment 457945 [details]
Patch
Comment 4 Per Arne Vollan 2022-04-22 13:23:13 PDT
Created attachment 458169 [details]
Patch
Comment 5 Per Arne Vollan 2022-04-25 08:11:12 PDT
Created attachment 458269 [details]
Patch
Comment 6 Per Arne Vollan 2022-04-25 09:11:04 PDT
Created attachment 458276 [details]
Patch
Comment 7 Radar WebKit Bug Importer 2022-04-25 14:22:10 PDT
<rdar://problem/92294145>
Comment 8 Per Arne Vollan 2022-04-25 14:23:18 PDT
<rdar://89758690>
Comment 9 Darin Adler 2022-04-25 14:49:47 PDT
Comment on attachment 458276 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=458276&action=review

> Source/WebKit/Shared/mac/AuxiliaryProcessMac.mm:824
> +    sandboxExtension->consume();

Why isn’t there code to do this the first time? Or if there is, why doesn’t this share code with it. Seems we also need to do this after process startup time even if the Open Directory cache was not invalidated.

> Source/WebKit/Shared/mac/AuxiliaryProcessMac.mm:826
> +    char buffer[4096];

Might need a comment saying why 4096 is the right number to use here.

> Source/WebKit/Shared/mac/AuxiliaryProcessMac.mm:827
> +    int bufferSize = sizeof(buffer);

Not sure we need to put this constant into an int. Just call sizeof(buffer) below.

> Source/WebKit/Shared/mac/AuxiliaryProcessMac.mm:829
> +    struct passwd pwd;
> +    struct passwd* result = 0;

This is C++, so I think you can write:

    passwd pwd;
    passwd* result = nullptr;

Don’t think we need struct and we don’t need to use 0.

> Source/WebKit/Shared/mac/AuxiliaryProcessMac.mm:830
> +    if (getpwuid_r(getuid(), &pwd, buffer, bufferSize, &result) || !result)

It’s incredibly non-obvious that the whole point of this call is to refill some internal caches with accurate data as a side effect, not use the result of this function at all.

I think there needs to be a comment explaining that this is an indirect way to revalidate caches so that calls done to related functions elsewhere in other frameworks get the correct result.

In my opinion it’s a bit fragile to rely on this property of the functions, not documented anywhere I can see, but it may well be necessary to do things this way. Needs a comment.

> Source/WebKit/Shared/mac/AuxiliaryProcessMac.mm:831
> +        WTFLogAlways("%s: Couldn't find home directory\n", getprogname());

Do we really need the "\n" here? Doesn’t WTFLog add it?

> Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm:712
> +    m_openDirectoryNotifyTokens.reserveCapacity(WTF_ARRAY_LENGTH(messages));

Can use std::size instead of WTF_ARRAY_LENGTH. We should probably get rid of WTF_ARRAY_LENGTH.

If this is always done exactly once we can use reserveInitialCapacity.

> Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm:713
> +    for (unsigned i = 0; i < WTF_ARRAY_LENGTH(messages); i++) {

Range-based for lop is bette for this:

    for (auto* message : messages) {
Comment 10 Per Arne Vollan 2022-04-26 09:04:39 PDT
Created attachment 458374 [details]
Patch
Comment 11 Per Arne Vollan 2022-04-26 09:07:30 PDT
Created attachment 458375 [details]
Patch
Comment 12 Per Arne Vollan 2022-04-26 10:19:32 PDT
(In reply to Darin Adler from comment #9)
> Comment on attachment 458276 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=458276&action=review
> 
> > Source/WebKit/Shared/mac/AuxiliaryProcessMac.mm:824
> > +    sandboxExtension->consume();
> 
> Why isn’t there code to do this the first time? Or if there is, why doesn’t
> this share code with it. Seems we also need to do this after process startup
> time even if the Open Directory cache was not invalidated.
> 

Ah, yes, that is a good point. We are currently calling getpwuid_r before entering the sandbox, which does not require the sandbox extension. I have added a new function getHomeDirectory in order to be able to share code.

> > Source/WebKit/Shared/mac/AuxiliaryProcessMac.mm:826
> > +    char buffer[4096];
> 
> Might need a comment saying why 4096 is the right number to use here.
> 

Looking at the man page for getpwuid_r, it seems the correct thing to do is to use the size returned from sysconf(_SC_GETPW_R_SIZE_MAX). So far, I have not changed this, since I believe a size of 4096 should be sufficient. PATH_MAX is 1024 according to sys limits.h. If you'd like, I can change this to use sysconf(_SC_GETPW_R_SIZE_MAX).

> > Source/WebKit/Shared/mac/AuxiliaryProcessMac.mm:827
> > +    int bufferSize = sizeof(buffer);
> 
> Not sure we need to put this constant into an int. Just call sizeof(buffer)
> below.
> 

Fixed!

> > Source/WebKit/Shared/mac/AuxiliaryProcessMac.mm:829
> > +    struct passwd pwd;
> > +    struct passwd* result = 0;
> 
> This is C++, so I think you can write:
> 
>     passwd pwd;
>     passwd* result = nullptr;
> 
> Don’t think we need struct and we don’t need to use 0.
> 

Done!

> > Source/WebKit/Shared/mac/AuxiliaryProcessMac.mm:830
> > +    if (getpwuid_r(getuid(), &pwd, buffer, bufferSize, &result) || !result)
> 
> It’s incredibly non-obvious that the whole point of this call is to refill
> some internal caches with accurate data as a side effect, not use the result
> of this function at all.
> 
> I think there needs to be a comment explaining that this is an indirect way
> to revalidate caches so that calls done to related functions elsewhere in
> other frameworks get the correct result.
> 
> In my opinion it’s a bit fragile to rely on this property of the functions,
> not documented anywhere I can see, but it may well be necessary to do things
> this way. Needs a comment.
> 

Comment added in AuxiliaryProcess::openDirectoryCacheInvalidated.

> > Source/WebKit/Shared/mac/AuxiliaryProcessMac.mm:831
> > +        WTFLogAlways("%s: Couldn't find home directory\n", getprogname());
> 
> Do we really need the "\n" here? Doesn’t WTFLog add it?
> 

Yes, removed "\n".

> > Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm:712
> > +    m_openDirectoryNotifyTokens.reserveCapacity(WTF_ARRAY_LENGTH(messages));
> 
> Can use std::size instead of WTF_ARRAY_LENGTH. We should probably get rid of
> WTF_ARRAY_LENGTH.
> 
> If this is always done exactly once we can use reserveInitialCapacity.
> 
> > Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm:713
> > +    for (unsigned i = 0; i < WTF_ARRAY_LENGTH(messages); i++) {
> 
> Range-based for lop is bette for this:
> 
>     for (auto* message : messages) {

Fixed!

Thanks for reviewing!
Comment 13 Darin Adler 2022-04-26 10:43:53 PDT
Comment on attachment 458276 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=458276&action=review

>>> Source/WebKit/Shared/mac/AuxiliaryProcessMac.mm:826
>>> +    char buffer[4096];
>> 
>> Might need a comment saying why 4096 is the right number to use here.
> 
> Looking at the man page for getpwuid_r, it seems the correct thing to do is to use the size returned from sysconf(_SC_GETPW_R_SIZE_MAX). So far, I have not changed this, since I believe a size of 4096 should be sufficient. PATH_MAX is 1024 according to sys limits.h. If you'd like, I can change this to use sysconf(_SC_GETPW_R_SIZE_MAX).

I saw that same man page and did not push you to use sysconf because it seemed like overkill given this is Apple-only code and doesn’t need to be portable to super-unusual configurations. On the other hand, I would be OK doing this entirely "by the book". Of course, since we are calling this to trigger a side effect, it’s kind of an "off-label" use anyway. I won’t push for further change, but do think a comment is good.
Comment 14 Per Arne Vollan 2022-04-26 10:57:23 PDT
Created attachment 458379 [details]
Patch
Comment 15 Per Arne Vollan 2022-04-26 11:00:31 PDT
(In reply to Darin Adler from comment #13)
> Comment on attachment 458276 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=458276&action=review
> 
> >>> Source/WebKit/Shared/mac/AuxiliaryProcessMac.mm:826
> >>> +    char buffer[4096];
> >> 
> >> Might need a comment saying why 4096 is the right number to use here.
> > 
> > Looking at the man page for getpwuid_r, it seems the correct thing to do is to use the size returned from sysconf(_SC_GETPW_R_SIZE_MAX). So far, I have not changed this, since I believe a size of 4096 should be sufficient. PATH_MAX is 1024 according to sys limits.h. If you'd like, I can change this to use sysconf(_SC_GETPW_R_SIZE_MAX).
> 
> I saw that same man page and did not push you to use sysconf because it
> seemed like overkill given this is Apple-only code and doesn’t need to be
> portable to super-unusual configurations. On the other hand, I would be OK
> doing this entirely "by the book". Of course, since we are calling this to
> trigger a side effect, it’s kind of an "off-label" use anyway. I won’t push
> for further change, but do think a comment is good.

I uploaded a new patch with a comment.

Thanks for reviewing!
Comment 16 EWS 2022-04-27 08:51:19 PDT
Committed r293509 (?): <https://commits.webkit.org/r293509>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 458379 [details].
Comment 17 Brent Fulgham 2022-06-23 15:31:36 PDT
*** Bug 237017 has been marked as a duplicate of this bug. ***