Bug 1916968

Summary: realpath sets errno to EINVAL on success
Product: [Fedora] Fedora Reporter: Jerry James <loganjerry>
Component: glibcAssignee: Carlos O'Donell <codonell>
Status: CLOSED NOTABUG QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: low Docs Contact:
Priority: unspecified    
Version: rawhideCC: aoliva, arjun, codonell, dj, fweimer, kdudka, law, mfabian, pfrankli, rth, sipoyare
Target Milestone: ---   
Target Release: ---   
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2021-01-18 21:59:39 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
Program demonstrating that realpath sets errno to EINVAL on success none

Description Jerry James 2021-01-16 00:49:59 UTC
Created attachment 1748055 [details]
Program demonstrating that realpath sets errno to EINVAL on success

Description of problem:
Koschei let me know today that the gcl package started failing to build.  Investigation shows that this is because realpath("/proc/self/exe", buffer) returns a pointer to buffer to indicate success, but also sets errno to EINVAL.  This is new behavior.  The attached program, when built and run on Fedora 33 and earlier, reports:

/proc/self/exe is a regular file
It's real path is [path to executable]
[path to executable]: Success

but in Rawhide it reports:

/proc/self/exe is a regular file
It's real path is [path to executable]
[path to executable]: Invalid argument

Version-Release number of selected component (if applicable):
glibc-2.32.9000-26.fc34.x86_64

How reproducible:
Always

Steps to Reproduce:
1. Compile the attached C program on Rawhide
2. Run it on Rawhide

Actual results:
See that realpath sets errno to EINVAL on success.

Expected results:
realpath should not touch errno or set it to zero on success

Additional info:

Comment 1 Florian Weimer 2021-01-16 10:41:41 UTC
In general, POSIX specifies that errno only has a valid value after an unsuccessful function call. glibc follows this policy.

What is the purpose of the errno check in gcl? It sounds like a bug in the code.

Comment 2 Jerry James 2021-01-18 21:05:25 UTC
It's part of a function that gcl uses to find a path to itself:

static int
mbin(const char *s,char *o) {
  struct stat ss;

  if (!stat(s,&ss) && (ss.st_mode&S_IFMT)==S_IFREG && !access(s,R_OK|X_OK)) {
    massert(realpath(s,o));
    return 1;
  }
  return 0;
}

where "massert" is a macro that sets errno to 0, evaluates its argument, then asserts that errno is still 0.

It looks like the BSD realpath() also follows the convention of returning NULL on error, so I'll talk to upstream about changing the assert.  Thanks for the reply, Florian.

Comment 3 Florian Weimer 2021-01-18 21:59:39 UTC
Interesting. On Linux, it's probably best to just read /proc/self/exe, or maybe use that directly (depending on the use case).

Anyway, thanks for providing the background. I don't think this is a glibc bug, so closing.