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_destroy_cred(struct scm_cookie *scm) 57 { 58 put_pid(scm->pid); 59 scm->pid = NULL; 60 61 if (scm->cred) 62 put_cred(scm->cred); 63 scm->cred = NULL; 64 } 65 66 static __inline__ void scm_destroy(struct scm_cookie *scm) 67 { 68 scm_destroy_cred(scm); 69 if (scm && scm->fp) 70 __scm_destroy(scm); 71 } 72 73 static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, 74 struct scm_cookie *scm) 75 { 76 scm_set_cred(scm, task_tgid(current), current_cred()); 77 scm->fp = NULL; 78 unix_get_peersec_dgram(sock, scm); 79 if (msg->msg_controllen <= 0) 80 return 0; 81 return __scm_send(sock, msg, scm); 82 } 83 84 #ifdef CONFIG_SECURITY_NETWORK 85 static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm) 86 { 87 char *secdata; 88 u32 seclen; 89 int err; 90 91 if (test_bit(SOCK_PASSSEC, &sock->flags)) { 92 err = security_secid_to_secctx(scm->secid, &secdata, &seclen); 93 94 if (!err) { 95 put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata); 96 security_release_secctx(secdata, seclen); 97 } 98 } 99 } 100 #else 101 static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm) 102 { } 103 #endif /* CONFIG_SECURITY_NETWORK */ 104 105 static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg, 106 struct scm_cookie *scm, int flags) 107 { 108 if (!msg->msg_control) { 109 if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp) 110 msg->msg_flags |= MSG_CTRUNC; 111 scm_destroy(scm); 112 return; 113 } 114 115 if (test_bit(SOCK_PASSCRED, &sock->flags)) 116 put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds); 117 118 scm_destroy_cred(scm); 119 120 scm_passec(sock, msg, scm); 121 122 if (!scm->fp) 123 return; 124 125 scm_detach_fds(msg, scm); 126 } 127 128 129 #endif /* __LINUX_NET_SCM_H */ 130 131