Skip to content

gh-89341: Support creation of a link to the file by fd #136302

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

serhiy-storchaka
Copy link
Member

@serhiy-storchaka serhiy-storchaka commented Jul 4, 2025

"test needs fd support in os.link()"
)
@unittest.skipUnless(root_in_posix,
"requires the CAP_DAC_READ_SEARCH capability")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On my Fedora 42, I can use AT_EMPTY_PATH as a regular user. I don't need to be root.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is difficult to check. What getpcaps $$ and cat /proc/$$/status | grep CapEff return to you.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vstinner@mona$ getpcaps $$
103445: cap_wake_alarm=i
vstinner@mona$ cat /proc/$$/status | grep CapEff
CapEff:	0000000000000000

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not look like your shell has such capability. Maybe Fedora has patches that ignores it?

@vstinner
Copy link
Member

vstinner commented Jul 8, 2025

My test which works as a normal user on Fedora 42:

import tempfile
import os
import ctypes

TESTNAME = b"linkat_test"

libc = ctypes.cdll.LoadLibrary("libc.so.6")
linkat = libc.linkat
linkat.argtypes = (
    ctypes.c_int,
    ctypes.c_char_p,
    ctypes.c_int,
    ctypes.c_char_p,
    ctypes.c_int,
)
linkat.restype = ctypes.c_int

AT_FDCWD = -100
AT_EMPTY_PATH = 0x1000

def link_file(fd):
    res = linkat(fd, b"",
                 AT_FDCWD, TESTNAME,
                 AT_EMPTY_PATH)
    if res:
        errno = ctypes.get_errno()
        print("linkat() failed: res", res, "errno", errno)
        raise OSError(errno)

try:
    os.unlink(TESTNAME)
except FileNotFoundError:
    pass

fd = os.open(".", os.O_WRONLY | os.O_TMPFILE)
os.write(fd, b"hello world\n")
link_file(fd)
os.close(fd)

with open(TESTNAME) as fp:
    print(fp.read(), end="")

os.unlink(TESTNAME)

@serhiy-storchaka
Copy link
Member Author

It fails on Ubuntu.

linkat() failed: res -1 errno 0
Traceback (most recent call last):
  File "/home/serhiy/py/cpython/t136302.py", line 37, in <module>
    link_file(fd)
    ~~~~~~~~~^^^^
  File "/home/serhiy/py/cpython/t136302.py", line 28, in link_file
    raise OSError(errno)
OSError: 0

@vstinner
Copy link
Member

vstinner commented Jul 8, 2025

I don't know why Fedora behaves differently. Kernel code:

	/*
	 * To use null names we require CAP_DAC_READ_SEARCH or
	 * that the open-time creds of the dfd matches current.
	 * This ensures that not everyone will be able to create
	 * a hardlink using the passed file descriptor.
	 */
	if (flags & AT_EMPTY_PATH)
		how |= LOOKUP_LINKAT_EMPTY;

@serhiy-storchaka
Copy link
Member Author

serhiy-storchaka commented Jul 8, 2025

I think that torvalds/linux@42bd2af is the cause.

There was no condition "or that the open-time creds of the dfd matches current" initially. This change makes the feature more usable.

I have pretty old kernel (was not able to boot with newer kernels after upgrade), so I cannot test this. I am not particularly interested in this feature. You can continue work (update the test, add the documentation) if you wish.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy