aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2008-07-24 00:29:17 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-24 13:47:27 -0400
commita677a039be7243357d93502bff2b40850c942e2d (patch)
tree6cf1669c4752e2527e02f33baa920cd2dfd59117
parent6e2c10a12a2170856f5582d62d583cbcd1cb5eaf (diff)
flag parameters: socket and socketpair
This patch adds support for flag values which are ORed to the type passwd to socket and socketpair. The additional code is minimal. The flag values in this implementation can and must match the O_* flags. This avoids overhead in the conversion. The internal functions sock_alloc_fd and sock_map_fd get a new parameters and all callers are changed. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <netinet/in.h> #include <sys/socket.h> #define PORT 57392 /* For Linux these must be the same. */ #define SOCK_CLOEXEC O_CLOEXEC int main (void) { int fd; fd = socket (PF_INET, SOCK_STREAM, 0); if (fd == -1) { puts ("socket(0) failed"); return 1; } int coe = fcntl (fd, F_GETFD); if (coe == -1) { puts ("fcntl failed"); return 1; } if (coe & FD_CLOEXEC) { puts ("socket(0) set close-on-exec flag"); return 1; } close (fd); fd = socket (PF_INET, SOCK_STREAM|SOCK_CLOEXEC, 0); if (fd == -1) { puts ("socket(SOCK_CLOEXEC) failed"); return 1; } coe = fcntl (fd, F_GETFD); if (coe == -1) { puts ("fcntl failed"); return 1; } if ((coe & FD_CLOEXEC) == 0) { puts ("socket(SOCK_CLOEXEC) does not set close-on-exec flag"); return 1; } close (fd); int fds[2]; if (socketpair (PF_UNIX, SOCK_STREAM, 0, fds) == -1) { puts ("socketpair(0) failed"); return 1; } for (int i = 0; i < 2; ++i) { coe = fcntl (fds[i], F_GETFD); if (coe == -1) { puts ("fcntl failed"); return 1; } if (coe & FD_CLOEXEC) { printf ("socketpair(0) set close-on-exec flag for fds[%d]\n", i); return 1; } close (fds[i]); } if (socketpair (PF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds) == -1) { puts ("socketpair(SOCK_CLOEXEC) failed"); return 1; } for (int i = 0; i < 2; ++i) { coe = fcntl (fds[i], F_GETFD); if (coe == -1) { puts ("fcntl failed"); return 1; } if ((coe & FD_CLOEXEC) == 0) { printf ("socketpair(SOCK_CLOEXEC) does not set close-on-exec flag for fds[%d]\n", i); return 1; } close (fds[i]); } 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: "David S. Miller" <davem@davemloft.net> Cc: Ralf Baechle <ralf@linux-mips.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/asm-mips/socket.h7
-rw-r--r--include/linux/net.h9
-rw-r--r--net/9p/trans_fd.c2
-rw-r--r--net/sctp/socket.c2
-rw-r--r--net/socket.c28
5 files changed, 37 insertions, 11 deletions
diff --git a/include/asm-mips/socket.h b/include/asm-mips/socket.h
index 63f60254d308..facc2d7a87ca 100644
--- a/include/asm-mips/socket.h
+++ b/include/asm-mips/socket.h
@@ -102,6 +102,13 @@ enum sock_type {
102}; 102};
103 103
104#define SOCK_MAX (SOCK_PACKET + 1) 104#define SOCK_MAX (SOCK_PACKET + 1)
105/* Mask which covers at least up to SOCK_MASK-1. The
106 * * remaining bits are used as flags. */
107#define SOCK_TYPE_MASK 0xf
108
109/* Flags for socket, socketpair, paccept */
110#define SOCK_CLOEXEC O_CLOEXEC
111#define SOCK_NONBLOCK O_NONBLOCK
105 112
106#define ARCH_HAS_SOCKET_TYPES 1 113#define ARCH_HAS_SOCKET_TYPES 1
107 114
diff --git a/include/linux/net.h b/include/linux/net.h
index 150a48c68d52..8b5383c45b45 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -20,6 +20,7 @@
20 20
21#include <linux/wait.h> 21#include <linux/wait.h>
22#include <linux/socket.h> 22#include <linux/socket.h>
23#include <linux/fcntl.h> /* For O_CLOEXEC */
23#include <asm/socket.h> 24#include <asm/socket.h>
24 25
25struct poll_table_struct; 26struct poll_table_struct;
@@ -94,6 +95,12 @@ enum sock_type {
94}; 95};
95 96
96#define SOCK_MAX (SOCK_PACKET + 1) 97#define SOCK_MAX (SOCK_PACKET + 1)
98/* Mask which covers at least up to SOCK_MASK-1. The
99 * remaining bits are used as flags. */
100#define SOCK_TYPE_MASK 0xf
101
102/* Flags for socket, socketpair, paccept */
103#define SOCK_CLOEXEC O_CLOEXEC
97 104
98#endif /* ARCH_HAS_SOCKET_TYPES */ 105#endif /* ARCH_HAS_SOCKET_TYPES */
99 106
@@ -208,7 +215,7 @@ extern int sock_sendmsg(struct socket *sock, struct msghdr *msg,
208 size_t len); 215 size_t len);
209extern int sock_recvmsg(struct socket *sock, struct msghdr *msg, 216extern int sock_recvmsg(struct socket *sock, struct msghdr *msg,
210 size_t size, int flags); 217 size_t size, int flags);
211extern int sock_map_fd(struct socket *sock); 218extern int sock_map_fd(struct socket *sock, int flags);
212extern struct socket *sockfd_lookup(int fd, int *err); 219extern struct socket *sockfd_lookup(int fd, int *err);
213#define sockfd_put(sock) fput(sock->file) 220#define sockfd_put(sock) fput(sock->file)
214extern int net_ratelimit(void); 221extern int net_ratelimit(void);
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index 4507f744f44e..cdf137af7adc 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -1285,7 +1285,7 @@ static int p9_socket_open(struct p9_trans *trans, struct socket *csocket)
1285 int fd, ret; 1285 int fd, ret;
1286 1286
1287 csocket->sk->sk_allocation = GFP_NOIO; 1287 csocket->sk->sk_allocation = GFP_NOIO;
1288 fd = sock_map_fd(csocket); 1288 fd = sock_map_fd(csocket, 0);
1289 if (fd < 0) { 1289 if (fd < 0) {
1290 P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to map fd\n"); 1290 P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to map fd\n");
1291 return fd; 1291 return fd;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 79bece16aede..dbb79adf8f3c 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3910,7 +3910,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval
3910 goto out; 3910 goto out;
3911 3911
3912 /* Map the socket to an unused fd that can be returned to the user. */ 3912 /* Map the socket to an unused fd that can be returned to the user. */
3913 retval = sock_map_fd(newsock); 3913 retval = sock_map_fd(newsock, 0);
3914 if (retval < 0) { 3914 if (retval < 0) {
3915 sock_release(newsock); 3915 sock_release(newsock);
3916 goto out; 3916 goto out;
diff --git a/net/socket.c b/net/socket.c
index 1ba57d888981..64601f900352 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -349,11 +349,11 @@ static struct dentry_operations sockfs_dentry_operations = {
349 * but we take care of internal coherence yet. 349 * but we take care of internal coherence yet.
350 */ 350 */
351 351
352static int sock_alloc_fd(struct file **filep) 352static int sock_alloc_fd(struct file **filep, int flags)
353{ 353{
354 int fd; 354 int fd;
355 355
356 fd = get_unused_fd(); 356 fd = get_unused_fd_flags(flags);
357 if (likely(fd >= 0)) { 357 if (likely(fd >= 0)) {
358 struct file *file = get_empty_filp(); 358 struct file *file = get_empty_filp();
359 359
@@ -396,10 +396,10 @@ static int sock_attach_fd(struct socket *sock, struct file *file)
396 return 0; 396 return 0;
397} 397}
398 398
399int sock_map_fd(struct socket *sock) 399int sock_map_fd(struct socket *sock, int flags)
400{ 400{
401 struct file *newfile; 401 struct file *newfile;
402 int fd = sock_alloc_fd(&newfile); 402 int fd = sock_alloc_fd(&newfile, flags);
403 403
404 if (likely(fd >= 0)) { 404 if (likely(fd >= 0)) {
405 int err = sock_attach_fd(sock, newfile); 405 int err = sock_attach_fd(sock, newfile);
@@ -1218,12 +1218,18 @@ asmlinkage long sys_socket(int family, int type, int protocol)
1218{ 1218{
1219 int retval; 1219 int retval;
1220 struct socket *sock; 1220 struct socket *sock;
1221 int flags;
1222
1223 flags = type & ~SOCK_TYPE_MASK;
1224 if (flags & ~SOCK_CLOEXEC)
1225 return -EINVAL;
1226 type &= SOCK_TYPE_MASK;
1221 1227
1222 retval = sock_create(family, type, protocol, &sock); 1228 retval = sock_create(family, type, protocol, &sock);
1223 if (retval < 0) 1229 if (retval < 0)
1224 goto out; 1230 goto out;
1225 1231
1226 retval = sock_map_fd(sock); 1232 retval = sock_map_fd(sock, flags & O_CLOEXEC);
1227 if (retval < 0) 1233 if (retval < 0)
1228 goto out_release; 1234 goto out_release;
1229 1235
@@ -1246,6 +1252,12 @@ asmlinkage long sys_socketpair(int family, int type, int protocol,
1246 struct socket *sock1, *sock2; 1252 struct socket *sock1, *sock2;
1247 int fd1, fd2, err; 1253 int fd1, fd2, err;
1248 struct file *newfile1, *newfile2; 1254 struct file *newfile1, *newfile2;
1255 int flags;
1256
1257 flags = type & ~SOCK_TYPE_MASK;
1258 if (flags & ~SOCK_CLOEXEC)
1259 return -EINVAL;
1260 type &= SOCK_TYPE_MASK;
1249 1261
1250 /* 1262 /*
1251 * Obtain the first socket and check if the underlying protocol 1263 * Obtain the first socket and check if the underlying protocol
@@ -1264,13 +1276,13 @@ asmlinkage long sys_socketpair(int family, int type, int protocol,
1264 if (err < 0) 1276 if (err < 0)
1265 goto out_release_both; 1277 goto out_release_both;
1266 1278
1267 fd1 = sock_alloc_fd(&newfile1); 1279 fd1 = sock_alloc_fd(&newfile1, flags & O_CLOEXEC);
1268 if (unlikely(fd1 < 0)) { 1280 if (unlikely(fd1 < 0)) {
1269 err = fd1; 1281 err = fd1;
1270 goto out_release_both; 1282 goto out_release_both;
1271 } 1283 }
1272 1284
1273 fd2 = sock_alloc_fd(&newfile2); 1285 fd2 = sock_alloc_fd(&newfile2, flags & O_CLOEXEC);
1274 if (unlikely(fd2 < 0)) { 1286 if (unlikely(fd2 < 0)) {
1275 err = fd2; 1287 err = fd2;
1276 put_filp(newfile1); 1288 put_filp(newfile1);
@@ -1426,7 +1438,7 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
1426 */ 1438 */
1427 __module_get(newsock->ops->owner); 1439 __module_get(newsock->ops->owner);
1428 1440
1429 newfd = sock_alloc_fd(&newfile); 1441 newfd = sock_alloc_fd(&newfile, 0);
1430 if (unlikely(newfd < 0)) { 1442 if (unlikely(newfd < 0)) {
1431 err = newfd; 1443 err = newfd;
1432 sock_release(newsock); 1444 sock_release(newsock);