tech-kern archive

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

Re: procfs files vs symlink



On Wed, 12 Jan 2022, Robert Elz wrote:

 | > What causes that EINVAL?
 |
 |
 | I'm not sure (somneone suggested that the file descriptor has been closed
 | when ls tries to fstat() it, but I can't confirm this).

That should generate EBADF not EINVAL.  Attempting readlink()
on something that is not a symlink, and various other possibilities
like that would be more probable.  EINVAL isn't listed as a possible
error return from [f]stat ... not that that guarantees that it cannot
happen, particularly from within emulation code.


That someone is me. But, your're right about this. The EINVAL is caused by
using readlink() on what was a symlink, but, is not anymore because the fd
now points to a regular file.

ktrace ls -l /proc/self/fd

  1954   1954 ls       CALL  open(0x7d9270fdc000,0x600004,3)
  1954   1954 ls       NAMI  "/proc/self/fd"
  1954   1954 ls       RET   open 4

  1954   1954 ls       CALL  fchdir(4)

  1954   1954 ls       CALL  __getdents30(4,0x7d9270fa6000,0x1000)

  1954   1954 ls       CALL  __lstat50(0x7d9270fd12f0,0x7d9270fd12f8)
  1954   1954 ls       NAMI  "0"
  1954   1954 ls       RET   __lstat50 0
  1954   1954 ls       CALL  __lstat50(0x7d9270fd1430,0x7d9270fd1438)
  1954   1954 ls       NAMI  "1"
  1954   1954 ls       RET   __lstat50 0
  1954   1954 ls       CALL  __lstat50(0x7d9270fd1570,0x7d9270fd1578)
  1954   1954 ls       NAMI  "2"
  1954   1954 ls       RET   __lstat50 0
  1954   1954 ls       CALL  __lstat50(0x7d9270fd16b0,0x7d9270fd16b8)
  1954   1954 ls       NAMI  "3"
  1954   1954 ls       RET   __lstat50 0
  1954   1954 ls       CALL  __lstat50(0x7d9270fd17f0,0x7d9270fd17f8)
  1954   1954 ls       NAMI  "4"

Up to this point fd 4 is a symlink which is, presumably, being
cached by ls(1).

  1954   1954 ls       CALL  close(4)

passwd db now opened at 4 which now is a regular file.

  1954   1954 ls       CALL  open(0x7d92705b0006,0x400000,0)
  1954   1954 ls       NAMI  "/etc/pwd.db"
  1954   1954 ls       RET   open 4

Now ls(1) does the listing:

  1954   1954 ls       GIO   fd 1 wrote 44 bytes
       "crw--w----  1 rvp  tty  5, 2 Jan 13 04:05 0\n"
  1954   1954 ls       RET   write 44/0x2c
  1954   1954 ls       CALL  write(1,0x7d9270fa2000,0x2c)
  1954   1954 ls       GIO   fd 1 wrote 44 bytes
       "crw--w----  1 rvp  tty  5, 2 Jan 13 04:05 1\n"
  1954   1954 ls       RET   write 44/0x2c
  1954   1954 ls       CALL  write(1,0x7d9270fa2000,0x2c)
  1954   1954 ls       GIO   fd 1 wrote 44 bytes
       "crw--w----  1 rvp  tty  5, 2 Jan 13 04:05 2\n"

  1954   1954 ls       CALL  readlink(0x7f7fff425a30,0x7f7fff425e40,0x400)
  1954   1954 ls       NAMI  "/proc/self/fd/3"
  1954   1954 ls       RET   readlink 4
  1954   1954 ls       CALL  write(1,0x7d9270fa2000,0x34)
  1954   1954 ls       GIO   fd 1 wrote 52 bytes
       "lr-xr-xr-x  1 rvp  rvp   240 Jan 13 04:05 3 -> /tmp\n"

The readlink on 4 will fail because it is no longer the symlink it
originally was:

  1954   1954 ls       CALL  readlink(0x7f7fff425a30,0x7f7fff425e40,0x400)
  1954   1954 ls       NAMI  "/proc/self/fd/4"
  1954   1954 ls       RET   readlink -1 errno 22 Invalid argument


Anyway, here's one more patch:

---START PATCH---
--- sys/miscfs/procfs/procfs_vnops.c.orig	2022-01-12 20:57:25.944841288 +0000
+++ sys/miscfs/procfs/procfs_vnops.c	2022-01-12 23:07:44.736070587 +0000
@@ -1410,7 +1410,7 @@
 			d.d_fileno = PROCFS_FILENO(pfs->pfs_pid, PFSfd, i - 2);
 			d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
 			    "%lld", (long long)(i - 2));
-			d.d_type = VREG;
+			d.d_type = DT_UNKNOWN;	/* convert vtype -> DT_XXX ? */
 			if ((error = uiomove(&d, UIO_MX, uio)) != 0)
 				break;
 			if (cookies)
---END PATCH---

DT_UNKNOWN is not quite right either, but that's better than VREG
which corresponds to DT_FIFO.

-RVP


Home | Main Index | Thread Index | Old Index