aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2008-07-24 00:29:30 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-24 13:47:28 -0400
commited8cae8ba01348bfd83333f4648dd807b04d7f08 (patch)
treec71a1c8e771c1c55728bb7c40612fbdcefbc858a /fs
parent336dd1f70ff62d7dd8655228caed4c5bfc818c56 (diff)
flag parameters: pipe
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/pipe.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/fs/pipe.c b/fs/pipe.c
index 700f4e0d9572..68e82061070c 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -1027,12 +1027,15 @@ struct file *create_read_pipe(struct file *wrf)
1027 return f; 1027 return f;
1028} 1028}
1029 1029
1030int do_pipe(int *fd) 1030int do_pipe_flags(int *fd, int flags)
1031{ 1031{
1032 struct file *fw, *fr; 1032 struct file *fw, *fr;
1033 int error; 1033 int error;
1034 int fdw, fdr; 1034 int fdw, fdr;
1035 1035
1036 if (flags & ~O_CLOEXEC)
1037 return -EINVAL;
1038
1036 fw = create_write_pipe(); 1039 fw = create_write_pipe();
1037 if (IS_ERR(fw)) 1040 if (IS_ERR(fw))
1038 return PTR_ERR(fw); 1041 return PTR_ERR(fw);
@@ -1041,12 +1044,12 @@ int do_pipe(int *fd)
1041 if (IS_ERR(fr)) 1044 if (IS_ERR(fr))
1042 goto err_write_pipe; 1045 goto err_write_pipe;
1043 1046
1044 error = get_unused_fd(); 1047 error = get_unused_fd_flags(flags);
1045 if (error < 0) 1048 if (error < 0)
1046 goto err_read_pipe; 1049 goto err_read_pipe;
1047 fdr = error; 1050 fdr = error;
1048 1051
1049 error = get_unused_fd(); 1052 error = get_unused_fd_flags(flags);
1050 if (error < 0) 1053 if (error < 0)
1051 goto err_fdr; 1054 goto err_fdr;
1052 fdw = error; 1055 fdw = error;
@@ -1074,16 +1077,21 @@ int do_pipe(int *fd)
1074 return error; 1077 return error;
1075} 1078}
1076 1079
1080int do_pipe(int *fd)
1081{
1082 return do_pipe_flags(fd, 0);
1083}
1084
1077/* 1085/*
1078 * sys_pipe() is the normal C calling standard for creating 1086 * sys_pipe() is the normal C calling standard for creating
1079 * a pipe. It's not the way Unix traditionally does this, though. 1087 * a pipe. It's not the way Unix traditionally does this, though.
1080 */ 1088 */
1081asmlinkage long __weak sys_pipe(int __user *fildes) 1089asmlinkage long __weak sys_pipe2(int __user *fildes, int flags)
1082{ 1090{
1083 int fd[2]; 1091 int fd[2];
1084 int error; 1092 int error;
1085 1093
1086 error = do_pipe(fd); 1094 error = do_pipe_flags(fd, flags);
1087 if (!error) { 1095 if (!error) {
1088 if (copy_to_user(fildes, fd, sizeof(fd))) { 1096 if (copy_to_user(fildes, fd, sizeof(fd))) {
1089 sys_close(fd[0]); 1097 sys_close(fd[0]);
@@ -1094,6 +1102,11 @@ asmlinkage long __weak sys_pipe(int __user *fildes)
1094 return error; 1102 return error;
1095} 1103}
1096 1104
1105asmlinkage long __weak sys_pipe(int __user *fildes)
1106{
1107 return sys_pipe2(fildes, 0);
1108}
1109
1097/* 1110/*
1098 * pipefs should _never_ be mounted by userland - too much of security hassle, 1111 * pipefs should _never_ be mounted by userland - too much of security hassle,
1099 * no real gain from having the whole whorehouse mounted. So we don't need 1112 * no real gain from having the whole whorehouse mounted. So we don't need