diff options
author | Ulrich Drepper <drepper@redhat.com> | 2008-07-24 00:29:17 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-24 13:47:27 -0400 |
commit | a677a039be7243357d93502bff2b40850c942e2d (patch) | |
tree | 6cf1669c4752e2527e02f33baa920cd2dfd59117 | |
parent | 6e2c10a12a2170856f5582d62d583cbcd1cb5eaf (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.h | 7 | ||||
-rw-r--r-- | include/linux/net.h | 9 | ||||
-rw-r--r-- | net/9p/trans_fd.c | 2 | ||||
-rw-r--r-- | net/sctp/socket.c | 2 | ||||
-rw-r--r-- | net/socket.c | 28 |
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 | ||
25 | struct poll_table_struct; | 26 | struct 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); |
209 | extern int sock_recvmsg(struct socket *sock, struct msghdr *msg, | 216 | extern int sock_recvmsg(struct socket *sock, struct msghdr *msg, |
210 | size_t size, int flags); | 217 | size_t size, int flags); |
211 | extern int sock_map_fd(struct socket *sock); | 218 | extern int sock_map_fd(struct socket *sock, int flags); |
212 | extern struct socket *sockfd_lookup(int fd, int *err); | 219 | extern struct socket *sockfd_lookup(int fd, int *err); |
213 | #define sockfd_put(sock) fput(sock->file) | 220 | #define sockfd_put(sock) fput(sock->file) |
214 | extern int net_ratelimit(void); | 221 | extern 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 | ||
352 | static int sock_alloc_fd(struct file **filep) | 352 | static 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 | ||
399 | int sock_map_fd(struct socket *sock) | 399 | int 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); |