aboutsummaryrefslogtreecommitdiffstats
path: root/net
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 /net
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>
Diffstat (limited to 'net')
-rw-r--r--net/9p/trans_fd.c2
-rw-r--r--net/sctp/socket.c2
-rw-r--r--net/socket.c28
3 files changed, 22 insertions, 10 deletions
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);