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 short count; 17 short max; 18 struct file *fp[SCM_MAX_FD]; 19 }; 20 21 struct scm_cookie { 22 struct pid *pid; /* Skb credentials */ 23 const struct cred *cred; 24 struct scm_fp_list *fp; /* Passed files */ 25 struct ucred creds; /* Skb credentials */ 26 #ifdef CONFIG_SECURITY_NETWORK 27 u32 secid; /* Passed security ID */ 28 #endif 29 }; 30 31 extern void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm); 32 extern void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm); 33 extern int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm); 34 extern void __scm_destroy(struct scm_cookie *scm); 35 extern struct scm_fp_list * scm_fp_dup(struct scm_fp_list *fpl); 36 37 #ifdef CONFIG_SECURITY_NETWORK 38 static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm) 39 { 40 security_socket_getpeersec_dgram(sock, NULL, &scm->secid); 41 } 42 #else 43 static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm) 44 { } 45 #endif /* CONFIG_SECURITY_NETWORK */ 46 47 static __inline__ void scm_set_cred(struct scm_cookie *scm, 48 struct pid *pid, const struct cred *cred) 49 { 50 scm->pid = get_pid(pid); 51 scm->cred = cred ? get_cred(cred) : NULL; 52 cred_to_ucred(pid, cred, &scm->creds); 53 } 54 55 static __inline__ void scm_destroy_cred(struct scm_cookie *scm) 56 { 57 put_pid(scm->pid); 58 scm->pid = NULL; 59 60 if (scm->cred) 61 put_cred(scm->cred); 62 scm->cred = NULL; 63 } 64 65 static __inline__ void scm_destroy(struct scm_cookie *scm) 66 { 67 scm_destroy_cred(scm); 68 if (scm && scm->fp) 69 __scm_destroy(scm); 70 } 71 72 static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, 73 struct scm_cookie *scm) 74 { 75 memset(scm, 0, sizeof(*scm)); 76 unix_get_peersec_dgram(sock, scm); 77 if (msg->msg_controllen <= 0) 78 return 0; 79 return __scm_send(sock, msg, scm); 80 } 81 82 #ifdef CONFIG_SECURITY_NETWORK 83 static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm) 84 { 85 char *secdata; 86 u32 seclen; 87 int err; 88 89 if (test_bit(SOCK_PASSSEC, &sock->flags)) { 90 err = security_secid_to_secctx(scm->secid, &secdata, &seclen); 91 92 if (!err) { 93 put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata); 94 security_release_secctx(secdata, seclen); 95 } 96 } 97 } 98 #else 99 static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm) 100 { } 101 #endif /* CONFIG_SECURITY_NETWORK */ 102 103 static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg, 104 struct scm_cookie *scm, int flags) 105 { 106 if (!msg->msg_control) { 107 if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp) 108 msg->msg_flags |= MSG_CTRUNC; 109 scm_destroy(scm); 110 return; 111 } 112 113 if (test_bit(SOCK_PASSCRED, &sock->flags)) 114 put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds); 115 116 scm_destroy_cred(scm); 117 118 scm_passec(sock, msg, scm); 119 120 if (!scm->fp) 121 return; 122 123 scm_detach_fds(msg, scm); 124 } 125 126 127 #endif /* __LINUX_NET_SCM_H */ 128 129