]>
Commit | Line | Data |
---|---|---|
ba9234d9 UD |
1 | /* Copyright (C) 1998 Free Software Foundation, Inc. |
2 | This file is part of the GNU C Library. | |
3 | ||
4 | The GNU C Library is free software; you can redistribute it and/or | |
5 | modify it under the terms of the GNU Library General Public License as | |
6 | published by the Free Software Foundation; either version 2 of the | |
7 | License, or (at your option) any later version. | |
8 | ||
9 | The GNU C Library is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | Library General Public License for more details. | |
13 | ||
14 | You should have received a copy of the GNU Library General Public | |
15 | License along with the GNU C Library; see the file COPYING.LIB. If not, | |
16 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
17 | Boston, MA 02111-1307, USA. */ | |
18 | ||
19 | #include <sys/socket.h> | |
20 | #include <errno.h> | |
c13de887 UD |
21 | #include <stdlib.h> |
22 | #include <string.h> | |
ba9234d9 UD |
23 | #include <unistd.h> |
24 | ||
25 | #include <asm/posix_types.h> | |
26 | ||
27 | /* The kernel expects this structure in SCM_CREDS messages. | |
28 | * Note: sizeof(struct __kernel_ucred) <= sizeof(struct cmsgcred) must hold. | |
29 | */ | |
c13de887 UD |
30 | struct kernel_ucred |
31 | { | |
32 | __kernel_pid_t pid; | |
33 | __kernel_uid_t uid; | |
34 | __kernel_gid_t gid; | |
35 | }; | |
36 | ||
37 | struct credmsg | |
38 | { | |
39 | struct cmsghdr cm; | |
40 | struct cmsgcred cc; | |
41 | }; | |
42 | ||
43 | struct kcredmsg | |
44 | { | |
45 | struct cmsghdr cm; | |
46 | struct kernel_ucred cc; | |
47 | }; | |
ba9234d9 | 48 | |
dd3c89f9 | 49 | extern int __syscall_sendmsg (int, const struct msghdr *, int); |
ba9234d9 UD |
50 | |
51 | /* Send a message described by MESSAGE on socket FD. | |
52 | Returns the number of bytes sent, or -1 for errors. */ | |
53 | int | |
7a68c94a | 54 | __libc_sendmsg (int fd, const struct msghdr *message, int flags) |
ba9234d9 | 55 | { |
c13de887 UD |
56 | struct msghdr m; |
57 | char *buf, *a, *b; | |
58 | struct credmsg *cred = 0; | |
59 | struct kcredmsg *kcred; | |
ba9234d9 | 60 | struct cmsghdr *cm; |
c13de887 | 61 | long int offset = 0; |
ba9234d9 UD |
62 | pid_t pid; |
63 | ||
64 | /* Preprocess the message control block for SCM_CREDS. */ | |
c13de887 | 65 | if (message->msg_controllen) |
ba9234d9 | 66 | { |
c13de887 UD |
67 | cm = CMSG_FIRSTHDR (message); |
68 | while (cm) | |
ba9234d9 | 69 | { |
c13de887 | 70 | if (cm->cmsg_type == SCM_CREDS) |
ba9234d9 | 71 | { |
c13de887 UD |
72 | if (cred || |
73 | cm->cmsg_len < CMSG_LEN (sizeof (struct cmsgcred))) | |
74 | { | |
75 | __set_errno (EINVAL); | |
76 | return -1; | |
77 | } | |
78 | else | |
79 | { | |
80 | cred = (struct credmsg *) cm; | |
81 | offset = (char *) cm - (char *) message->msg_control; | |
82 | } | |
ba9234d9 | 83 | } |
c13de887 UD |
84 | cm = CMSG_NXTHDR ((struct msghdr *) message, cm); |
85 | } | |
86 | ||
87 | if (cred) | |
88 | { | |
89 | buf = alloca (message->msg_controllen); | |
90 | memcpy (buf, message->msg_control, message->msg_controllen); | |
91 | kcred = (struct kcredmsg *) (buf + offset); | |
92 | a = (char *) kcred + CMSG_LEN (sizeof (struct kernel_ucred)); | |
93 | b = (char *) kcred + CMSG_LEN (sizeof (struct cmsgcred)); | |
94 | memmove (a, b, message->msg_controllen - (b - buf)); | |
95 | ||
96 | kcred->cm.cmsg_len = CMSG_LEN (sizeof (struct kernel_ucred)); | |
ba9234d9 | 97 | |
ba9234d9 UD |
98 | /* Linux expects the calling process to pass in |
99 | its credentials, and sanity checks them. | |
100 | You can send real, effective, or set- uid and gid. | |
101 | If the user hasn't filled in the buffer, we default to | |
102 | real uid and gid. */ | |
50304ef0 | 103 | pid = __getpid (); |
c13de887 UD |
104 | if (cred->cc.cmcred_pid != pid) |
105 | { | |
106 | kcred->cc.pid = pid; | |
107 | kcred->cc.uid = __getuid (); | |
108 | kcred->cc.gid = __getgid (); | |
109 | } | |
ba9234d9 | 110 | else |
c13de887 UD |
111 | { |
112 | kcred->cc.uid = cred->cc.cmcred_uid; | |
113 | kcred->cc.gid = cred->cc.cmcred_gid; | |
114 | } | |
115 | memcpy (&m, message, sizeof (struct msghdr)); | |
116 | m.msg_control = buf; | |
117 | m.msg_controllen -= b - a; | |
118 | return __syscall_sendmsg (fd, &m, flags); | |
ba9234d9 | 119 | } |
ba9234d9 | 120 | } |
dd3c89f9 | 121 | return __syscall_sendmsg (fd, message, flags); |
ba9234d9 | 122 | } |
dd3c89f9 | 123 | |
dd3c89f9 | 124 | weak_alias (__libc_sendmsg, sendmsg) |