bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

readlink("/proc/self/exe") with glibc 2.28 is broken?


From: Ludovic Courtès
Subject: readlink("/proc/self/exe") with glibc 2.28 is broken?
Date: Sat, 15 Dec 2018 18:47:46 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/26.1 (gnu/linux)

Hello hacker herd!

The attached C code reads /proc/self/exe.  I tested it on darnassus in
two contexts:

  1. Natively compiled with the Debian toolchain available on darnassus;

  2. Cross-built with the GNU toolchain (which includes stock
     glibc 2.28) found in Guix, statically-linked.

#1 works as expected whereas for #2 readlink("/proc/self/exe") returns
EGRATUITOUS; #2 works for other symlinks though.

rpctrace shows that Guix’s libc doesn’t behave like Debian’s on
darnassus.  Namely, Guix libc 2.28 does this:

--8<---------------cut here---------------start------------->8---
  137<--176(pid8674)->dir_lookup ("proc/self/exe" 65 0) = 0 1 "self/exe"    
191<--190(pid8674)
  191<--190(pid8674)->dir_lookup ("self/exe" 65 0) = 0 3 "pid/exe"  (null)
task163(pid8674)->mach_port_deallocate (pn{ 20}) = 0 
task163(pid8674)->mach_port_mod_refs (pn{  7} 0 1) = 0 
task163(pid8674)->mach_port_mod_refs (pn{ 19} 0 1) = 0 
  124<--174(pid8674)->io_get_openmodes () = 0 3
  124<--174(pid8674)->io_stat () = 0 {14 21405 0 0 0 1437067240 0 8397200 1 
1006 5 0 0 1544895840 0 1544895840 0 1544895840 0 512 8 0 0 0 136648208 3259 0 
0 1315456 3261 136650912 3262}
  189<--188(pid8674)->io_write ("readlink: Gratuitous error\n" -1)readlink: 
Gratuitous error
 = 0 27
--8<---------------cut here---------------end--------------->8---

… whereas Debian’s libc does:

--8<---------------cut here---------------start------------->8---
  137<--176(pid8678)->dir_lookup ("proc/self/exe" 65 0) = 0 1 "self/exe"    
192<--191(pid8678)
task163(pid8678)->mach_port_mod_refs (pn{ 21} 0 1) = 0 
  192<--191(pid8678)->dir_lookup ("self/exe" 65 0) = 0 3 "pid/exe"  (null)
task163(pid8678)->mach_port_deallocate (pn{ 21}) = 0 
task163(pid8678)->mach_port_mod_refs (pn{ 21} 0 1) = 0 
  192<--191(pid8678)->dir_lookup ("8678/exe" 65 0) = 0 1 ""    
194<--193(pid8678)
task163(pid8678)->mach_port_deallocate (pn{ 21}) = 0 
task163(pid8678)->mach_port_deallocate (pn{ 21}) = 0 
  194<--193(pid8678)->io_stat () = 0 {0 0 0 -395048269 0 0 0 41471 0 1006 0 18 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}
  194<--193(pid8678)->io_read (0 256) = 0 "./cross-built.dynl"
task163(pid8678)->mach_port_deallocate (pn{ 22}) = 0 
  139<--173(pid8678)->io_stat () = 0 {14 21405 0 0 0 1437067240 0 8397200 1 
1006 5 0 0 1544895879 0 1544895879 0 1544895879 0 512 8 0 0 0 136648208 3259 0 
0 1315456 3261 136650912 3262}
  188<--166(pid8678)->io_write ("readlink ("/proc/self/exe") = 
"./cross-built.dynl"\n" -1)readlink ("/proc/self/exe") = "./cross-built.dynl"
 = 0 51
--8<---------------cut here---------------end--------------->8---

So Debian libc (presumably ‘file_name_lookup’) is doing more work, which
proves to be useful.  :-)

Am I missing anything obvious to you?  For example, are there patches
that Debian uses and that upstream 2.28 still lacks?

Thanks in advance!

Ludo’.

#define _GNU_SOURCE 1
#include <stdlib.h>
#include <unistd.h>
#include <libgen.h>
#include <errno.h>
#include <stdio.h>

int
main (int argc, char *argv[])
{
  ssize_t ret;
  char program[256] = { 0, };
  const char *arg = (argc > 1) ? argv[1] : "/proc/self/exe";

  ret = readlink (arg, program, sizeof program);
  if (ret < 0)
    perror ("readlink");

  printf ("readlink (\"%s\") = \"%s\"\n", arg, program);

  return 0;
}

reply via email to

[Prev in Thread] Current Thread [Next in Thread]