Skip to content

Commit

Permalink
flag parameters: pipe
Browse files Browse the repository at this point in the history
This patch introduces the new syscall pipe2 which is like pipe but it also
takes an additional parameter which takes a flag value.  This patch implements
the handling of O_CLOEXEC for the flag.  I did not add support for the new
syscall for the architectures which have a special sys_pipe implementation.  I
think the maintainers of those archs have the chance to go with the unified
implementation but that's up to them.

The implementation introduces do_pipe_flags.  I did that instead of changing
all callers of do_pipe because some of the callers are written in assembler.
I would probably screw up changing the assembly code.  To avoid breaking code
do_pipe is now a small wrapper around do_pipe_flags.  Once all callers are
changed over to do_pipe_flags the old do_pipe function can be removed.

The following test must be adjusted for architectures other than x86 and
x86-64 and in case the syscall numbers changed.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>

#ifndef __NR_pipe2
# ifdef __x86_64__
#  define __NR_pipe2 293
# elif defined __i386__
#  define __NR_pipe2 331
# else
#  error "need __NR_pipe2"
# endif
#endif

int
main (void)
{
  int fd[2];
  if (syscall (__NR_pipe2, fd, 0) != 0)
    {
      puts ("pipe2(0) failed");
      return 1;
    }
  for (int i = 0; i < 2; ++i)
    {
      int coe = fcntl (fd[i], F_GETFD);
      if (coe == -1)
        {
          puts ("fcntl failed");
          return 1;
        }
      if (coe & FD_CLOEXEC)
        {
          printf ("pipe2(0) set close-on-exit for fd[%d]\n", i);
          return 1;
        }
    }
  close (fd[0]);
  close (fd[1]);

  if (syscall (__NR_pipe2, fd, O_CLOEXEC) != 0)
    {
      puts ("pipe2(O_CLOEXEC) failed");
      return 1;
    }
  for (int i = 0; i < 2; ++i)
    {
      int coe = fcntl (fd[i], F_GETFD);
      if (coe == -1)
        {
          puts ("fcntl failed");
          return 1;
        }
      if ((coe & FD_CLOEXEC) == 0)
        {
          printf ("pipe2(O_CLOEXEC) does not set close-on-exit for fd[%d]\n", i);
          return 1;
        }
    }
  close (fd[0]);
  close (fd[1]);

  puts ("OK");

  return 0;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Signed-off-by: Ulrich Drepper <drepper@redhat.com>
Acked-by: Davide Libenzi <davidel@xmailserver.org>
Cc: Michael Kerrisk <mtk.manpages@googlemail.com>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Ulrich Drepper authored and Linus Torvalds committed Jul 24, 2008
1 parent 336dd1f commit ed8cae8
Show file tree
Hide file tree
Showing 15 changed files with 33 additions and 14 deletions.
2 changes: 1 addition & 1 deletion arch/ia64/ia32/sys_ia32.c
Original file line number Diff line number Diff line change
Expand Up @@ -1139,7 +1139,7 @@ sys32_pipe (int __user *fd)
int retval;
int fds[2];

retval = do_pipe(fds);
retval = do_pipe_flags(fds, 0);
if (retval)
goto out;
if (copy_to_user(fd, fds, sizeof(fds)))
Expand Down
2 changes: 1 addition & 1 deletion arch/ia64/kernel/sys_ia64.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ sys_pipe (void)
int fd[2];
int retval;

retval = do_pipe(fd);
retval = do_pipe_flags(fd, 0);
if (retval)
goto out;
retval = fd[0];
Expand Down
2 changes: 1 addition & 1 deletion arch/mips/kernel/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ asmlinkage int sysm_pipe(nabi_no_regargs volatile struct pt_regs regs)
int fd[2];
int error, res;

error = do_pipe(fd);
error = do_pipe_flags(fd, 0);
if (error) {
res = error;
goto out;
Expand Down
2 changes: 1 addition & 1 deletion arch/parisc/hpux/sys_hpux.c
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ int hpux_pipe(int *kstack_fildes)
int error;

lock_kernel();
error = do_pipe(kstack_fildes);
error = do_pipe_flags(kstack_fildes, 0);
unlock_kernel();
return error;
}
Expand Down
2 changes: 1 addition & 1 deletion arch/sh/kernel/sys_sh32.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ asmlinkage int sys_pipe(unsigned long r4, unsigned long r5,
int fd[2];
int error;

error = do_pipe(fd);
error = do_pipe_flags(fd, 0);
if (!error) {
regs->regs[1] = fd[1];
return fd[0];
Expand Down
2 changes: 1 addition & 1 deletion arch/sparc/kernel/sys_sparc.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ asmlinkage int sparc_pipe(struct pt_regs *regs)
int fd[2];
int error;

error = do_pipe(fd);
error = do_pipe_flags(fd, 0);
if (error)
goto out;
regs->u_regs[UREG_I1] = fd[1];
Expand Down
2 changes: 1 addition & 1 deletion arch/sparc64/kernel/sys_sparc.c
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ asmlinkage long sparc_pipe(struct pt_regs *regs)
int fd[2];
int error;

error = do_pipe(fd);
error = do_pipe_flags(fd, 0);
if (error)
goto out;
regs->u_regs[UREG_I1] = fd[1];
Expand Down
1 change: 1 addition & 0 deletions arch/x86/ia32/ia32entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -830,4 +830,5 @@ ia32_sys_call_table:
.quad sys_eventfd2
.quad sys_epoll_create2
.quad sys_dup3 /* 330 */
.quad sys_pipe2
ia32_syscall_end:
2 changes: 1 addition & 1 deletion arch/x86/ia32/sys_ia32.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ asmlinkage long sys32_pipe(int __user *fd)
int retval;
int fds[2];

retval = do_pipe(fds);
retval = do_pipe_flags(fds, 0);
if (retval)
goto out;
if (copy_to_user(fd, fds, sizeof(fds)))
Expand Down
1 change: 1 addition & 0 deletions arch/x86/kernel/syscall_table_32.S
Original file line number Diff line number Diff line change
Expand Up @@ -330,3 +330,4 @@ ENTRY(sys_call_table)
.long sys_eventfd2
.long sys_epoll_create2
.long sys_dup3 /* 330 */
.long sys_pipe2
2 changes: 1 addition & 1 deletion arch/xtensa/kernel/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ asmlinkage long xtensa_pipe(int __user *userfds)
int fd[2];
int error;

error = do_pipe(fd);
error = do_pipe_flags(fd, 0);
if (!error) {
if (copy_to_user(userfds, fd, 2 * sizeof(int)))
error = -EFAULT;
Expand Down
23 changes: 18 additions & 5 deletions fs/pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -1027,12 +1027,15 @@ struct file *create_read_pipe(struct file *wrf)
return f;
}

int do_pipe(int *fd)
int do_pipe_flags(int *fd, int flags)
{
struct file *fw, *fr;
int error;
int fdw, fdr;

if (flags & ~O_CLOEXEC)
return -EINVAL;

fw = create_write_pipe();
if (IS_ERR(fw))
return PTR_ERR(fw);
Expand All @@ -1041,12 +1044,12 @@ int do_pipe(int *fd)
if (IS_ERR(fr))
goto err_write_pipe;

error = get_unused_fd();
error = get_unused_fd_flags(flags);
if (error < 0)
goto err_read_pipe;
fdr = error;

error = get_unused_fd();
error = get_unused_fd_flags(flags);
if (error < 0)
goto err_fdr;
fdw = error;
Expand Down Expand Up @@ -1074,16 +1077,21 @@ int do_pipe(int *fd)
return error;
}

int do_pipe(int *fd)
{
return do_pipe_flags(fd, 0);
}

/*
* sys_pipe() is the normal C calling standard for creating
* a pipe. It's not the way Unix traditionally does this, though.
*/
asmlinkage long __weak sys_pipe(int __user *fildes)
asmlinkage long __weak sys_pipe2(int __user *fildes, int flags)
{
int fd[2];
int error;

error = do_pipe(fd);
error = do_pipe_flags(fd, flags);
if (!error) {
if (copy_to_user(fildes, fd, sizeof(fd))) {
sys_close(fd[0]);
Expand All @@ -1094,6 +1102,11 @@ asmlinkage long __weak sys_pipe(int __user *fildes)
return error;
}

asmlinkage long __weak sys_pipe(int __user *fildes)
{
return sys_pipe2(fildes, 0);
}

/*
* pipefs should _never_ be mounted by userland - too much of security hassle,
* no real gain from having the whole whorehouse mounted. So we don't need
Expand Down
1 change: 1 addition & 0 deletions include/asm-x86/unistd_32.h
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@
#define __NR_eventfd2 328
#define __NR_epoll_create2 329
#define __NR_dup3 330
#define __NR_pipe2 331

#ifdef __KERNEL__

Expand Down
2 changes: 2 additions & 0 deletions include/asm-x86/unistd_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,8 @@ __SYSCALL(__NR_eventfd2, sys_eventfd2)
__SYSCALL(__NR_epoll_create2, sys_epoll_create2)
#define __NR_dup3 292
__SYSCALL(__NR_dup3, sys_dup3)
#define __NR_pipe2 293
__SYSCALL(__NR_pipe2, sys_pipe2)


#ifndef __NO_STUBS
Expand Down
1 change: 1 addition & 0 deletions include/linux/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1777,6 +1777,7 @@ static inline void allow_write_access(struct file *file)
atomic_inc(&file->f_path.dentry->d_inode->i_writecount);
}
extern int do_pipe(int *);
extern int do_pipe_flags(int *, int);
extern struct file *create_read_pipe(struct file *f);
extern struct file *create_write_pipe(void);
extern void free_write_pipe(struct file *);
Expand Down

0 comments on commit ed8cae8

Please sign in to comment.