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 8 /* Well, we should have at least one descriptor open 9 * to accept passed FDs 8) 10 */ 11 #define SCM_MAX_FD (OPEN_MAX-1) 12 13 struct scm_fp_list 14 { 15 int count; 16 struct file *fp[SCM_MAX_FD]; 17 }; 18 19 struct scm_cookie 20 { 21 struct ucred creds; /* Skb credentials */ 22 struct scm_fp_list *fp; /* Passed files */ 23 #ifdef CONFIG_SECURITY_NETWORK 24 u32 secid; /* Passed security ID */ 25 #endif 26 unsigned long seq; /* Connection seqno */ 27 }; 28 29 extern void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm); 30 extern void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm); 31 extern int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm); 32 extern void __scm_destroy(struct scm_cookie *scm); 33 extern struct scm_fp_list * scm_fp_dup(struct scm_fp_list *fpl); 34 35 #ifdef CONFIG_SECURITY_NETWORK 36 static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm) 37 { 38 security_socket_getpeersec_dgram(sock, NULL, &scm->secid); 39 } 40 #else 41 static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm) 42 { } 43 #endif /* CONFIG_SECURITY_NETWORK */ 44 45 static __inline__ void scm_destroy(struct scm_cookie *scm) 46 { 47 if (scm && scm->fp) 48 __scm_destroy(scm); 49 } 50 51 static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, 52 struct scm_cookie *scm) 53 { 54 struct task_struct *p = current; 55 scm->creds.uid = p->uid; 56 scm->creds.gid = p->gid; 57 scm->creds.pid = p->tgid; 58 scm->fp = NULL; 59 scm->seq = 0; 60 unix_get_peersec_dgram(sock, scm); 61 if (msg->msg_controllen <= 0) 62 return 0; 63 return __scm_send(sock, msg, scm); 64 } 65 66 #ifdef CONFIG_SECURITY_NETWORK 67 static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm) 68 { 69 char *secdata; 70 u32 seclen; 71 int err; 72 73 if (test_bit(SOCK_PASSSEC, &sock->flags)) { 74 err = security_secid_to_secctx(scm->secid, &secdata, &seclen); 75 76 if (!err) { 77 put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata); 78 security_release_secctx(secdata, seclen); 79 } 80 } 81 } 82 #else 83 static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm) 84 { } 85 #endif /* CONFIG_SECURITY_NETWORK */ 86 87 static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg, 88 struct scm_cookie *scm, int flags) 89 { 90 if (!msg->msg_control) 91 { 92 if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp) 93 msg->msg_flags |= MSG_CTRUNC; 94 scm_destroy(scm); 95 return; 96 } 97 98 if (test_bit(SOCK_PASSCRED, &sock->flags)) 99 put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds); 100 101 scm_passec(sock, msg, scm); 102 103 if (!scm->fp) 104 return; 105 106 scm_detach_fds(msg, scm); 107 } 108 109 110 #endif /* __LINUX_NET_SCM_H */ 111 112