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

Bug#990244: tests/streams: Failing test on pipe stdout file descriptor

Hi Dennis,

Thanks for your helpful feedback.

On 6/26/21 6:02 AM, Dennis Filder wrote:
> Control: tags -1 moreinfo
> X-Debbugs-CC: Ariel D'Alessandro <ariel.dalessandro@collabora.com>
> It could be that OBS opens the pipe as a privileged process, forks,
> then drops privileges afterwards such that the child process is
> precluded from reopening the inode that backs the file descriptor
> clisp operates on.

Makes sense, agreed, this is probably the sequence.

> You'd somehow have to find a way to invoke "stat -L
> /proc/<pid>/fd/<fdno>" on the failing file quickly enough to find out
> if this is the case.  Inserting sleeps into the test could buy you
> more time.

The clisp stream test is failing here:

lstat("/proc/1880876/fd/2", {st_mode=S_IFLNK|0300, st_size=64, ...}) = 0
readlink("/proc/1880876/fd/2", "pipe:[53088390]", 64) = 15
stat("/proc/1880876/fd/2", {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
openat(AT_FDCWD, "/proc/1880876/fd/2", O_WRONLY|O_CREAT|O_TRUNC, 0644) =
-1 EACCES (Permission denied)

This matches the case described above, opening the pipe as root, then
dropping and running clisp (during tests):

$ stat -L proc/1880876/fd/2
  File: proc/1880876/fd/2
  Size: 0         	Blocks: 0          IO Block: 4096   fifo
Device: ch/12d	Inode: 53088390    Links: 1
Access: (0600/prw-------)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2021-12-09 21:55:16.645805190 -0300
Modify: 2021-12-09 21:55:16.645805190 -0300
Change: 2021-12-09 21:55:16.645805190 -0300
 Birth: -

$ head proc/1880876/status
Name:	lisp.run
Umask:	0022
State:	S (sleeping)
Tgid:	1880876
Ngid:	0
Pid:	1880876
PPid:	1880873
TracerPid:	1880873
Uid:	399	399	399	399
Gid:	399	399	399	399

> Alternatively (and assuming you use ocs) tools like socat/ptywrap
> could maybe be used via $OSC_SU_WRAPPER to hook the child process onto
> a pty (which should also be created after dropping the privileges).
> Or you could try to run the build as root (osc build
> --userootforbuild) and see if the error persists.

Did a quick check by running the lisp tests using ptywrap and the error
is no longer happening. Of course, now the pty is used instead of the
(root owned) pipe, so permissions are fine to re-open the file.

So, moving forward. This is the failing test simplified:

(streamp (setq s (make-stream :error))) T
(let ((*reopen-open-file* nil)) ; stdout can be a file, it will be detected!
  (with-open-file (copy s :direction :output) (streamp copy))) T

My question here would be: is this test expected to always succeed?

AFAIU, we can't assume to have the permissions to re-open the file
related to the file descriptor, which is what the code is explicitly
trying to do.

Please correct me if I'm wrong as I'm not used to clisp syntax, just
going through the source code :-)

>From what I see, it responsibility of the clisp test code to check if it
has the permissions to re-open the file. Otherwise, it's not guaranteed
to succeed. For example, having this fd pointing to a (root owned) pipe
is a valid situation and should be properly handled by this test.


Reply to: