68e1e481658e0724a0afecd5ab5ea27d4ced768c
[linux-3.10.git] / include / net / scm.h
1 #ifndef __LINUX_NET_SCM_H
2 #define __LINUX_NET_SCM_H
3
4 #include <linux/limits.h>
5 #include <linux/net.h>
6 #include <linux/security.h>
7 #include <linux/pid.h>
8 #include <linux/nsproxy.h>
9
10 /* Well, we should have at least one descriptor open
11  * to accept passed FDs 8)
12  */
13 #define SCM_MAX_FD      253
14
15 struct scm_fp_list {
16         struct list_head        list;
17         short                   count;
18         short                   max;
19         struct file             *fp[SCM_MAX_FD];
20 };
21
22 struct scm_cookie {
23         struct pid              *pid;           /* Skb credentials */
24         const struct cred       *cred;
25         struct scm_fp_list      *fp;            /* Passed files         */
26         struct ucred            creds;          /* Skb credentials      */
27 #ifdef CONFIG_SECURITY_NETWORK
28         u32                     secid;          /* Passed security ID   */
29 #endif
30 };
31
32 extern void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm);
33 extern void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm);
34 extern int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm);
35 extern void __scm_destroy(struct scm_cookie *scm);
36 extern struct scm_fp_list * scm_fp_dup(struct scm_fp_list *fpl);
37
38 #ifdef CONFIG_SECURITY_NETWORK
39 static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm)
40 {
41         security_socket_getpeersec_dgram(sock, NULL, &scm->secid);
42 }
43 #else
44 static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm)
45 { }
46 #endif /* CONFIG_SECURITY_NETWORK */
47
48 static __inline__ void scm_set_cred(struct scm_cookie *scm,
49                                     struct pid *pid, const struct cred *cred)
50 {
51         scm->pid  = get_pid(pid);
52         scm->cred = get_cred(cred);
53         cred_to_ucred(pid, cred, &scm->creds);
54 }
55
56 static __inline__ void scm_set_cred_noref(struct scm_cookie *scm,
57                                     struct pid *pid, const struct cred *cred)
58 {
59         scm->pid  = pid;
60         scm->cred = cred;
61         cred_to_ucred(pid, cred, &scm->creds);
62 }
63
64 static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
65 {
66         put_pid(scm->pid);
67         scm->pid  = NULL;
68
69         if (scm->cred)
70                 put_cred(scm->cred);
71         scm->cred = NULL;
72 }
73
74 static __inline__ void scm_destroy(struct scm_cookie *scm)
75 {
76         scm_destroy_cred(scm);
77         if (scm && scm->fp)
78                 __scm_destroy(scm);
79 }
80
81 static __inline__ void scm_release(struct scm_cookie *scm)
82 {
83         /* keep ref on pid and cred */
84         scm->pid = NULL;
85         scm->cred = NULL;
86         if (scm->fp)
87                 __scm_destroy(scm);
88 }
89
90 static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
91                                struct scm_cookie *scm)
92 {
93         scm_set_cred(scm, task_tgid(current), current_cred());
94         scm->fp = NULL;
95         unix_get_peersec_dgram(sock, scm);
96         if (msg->msg_controllen <= 0)
97                 return 0;
98         return __scm_send(sock, msg, scm);
99 }
100
101 #ifdef CONFIG_SECURITY_NETWORK
102 static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
103 {
104         char *secdata;
105         u32 seclen;
106         int err;
107
108         if (test_bit(SOCK_PASSSEC, &sock->flags)) {
109                 err = security_secid_to_secctx(scm->secid, &secdata, &seclen);
110
111                 if (!err) {
112                         put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata);
113                         security_release_secctx(secdata, seclen);
114                 }
115         }
116 }
117 #else
118 static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
119 { }
120 #endif /* CONFIG_SECURITY_NETWORK */
121
122 static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
123                                 struct scm_cookie *scm, int flags)
124 {
125         if (!msg->msg_control) {
126                 if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp)
127                         msg->msg_flags |= MSG_CTRUNC;
128                 if (scm && scm->fp)
129                         __scm_destroy(scm);
130                 return;
131         }
132
133         if (test_bit(SOCK_PASSCRED, &sock->flags))
134                 put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds);
135
136         scm_passec(sock, msg, scm);
137
138         if (!scm->fp)
139                 return;
140         
141         scm_detach_fds(msg, scm);
142 }
143
144
145 #endif /* __LINUX_NET_SCM_H */
146