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 255 14 15struct scm_fp_list { 16 struct list_head list; 17 int count; 18 struct file *fp[SCM_MAX_FD]; 19}; 20 21struct 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 31extern void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm); 32extern void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm); 33extern int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm); 34extern void __scm_destroy(struct scm_cookie *scm); 35extern struct scm_fp_list * scm_fp_dup(struct scm_fp_list *fpl); 36 37#ifdef CONFIG_SECURITY_NETWORK 38static __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 43static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm) 44{ } 45#endif /* CONFIG_SECURITY_NETWORK */ 46 47static __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 = get_cred(cred); 52 cred_to_ucred(pid, cred, &scm->creds); 53} 54 55static __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 65static __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 72static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, 73 struct scm_cookie *scm) 74{ 75 scm_set_cred(scm, task_tgid(current), current_cred()); 76 scm->fp = NULL; 77 unix_get_peersec_dgram(sock, scm); 78 if (msg->msg_controllen <= 0) 79 return 0; 80 return __scm_send(sock, msg, scm); 81} 82 83#ifdef CONFIG_SECURITY_NETWORK 84static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm) 85{ 86 char *secdata; 87 u32 seclen; 88 int err; 89 90 if (test_bit(SOCK_PASSSEC, &sock->flags)) { 91 err = security_secid_to_secctx(scm->secid, &secdata, &seclen); 92 93 if (!err) { 94 put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata); 95 security_release_secctx(secdata, seclen); 96 } 97 } 98} 99#else 100static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm) 101{ } 102#endif /* CONFIG_SECURITY_NETWORK */ 103 104static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg, 105 struct scm_cookie *scm, int flags) 106{ 107 if (!msg->msg_control) { 108 if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp) 109 msg->msg_flags |= MSG_CTRUNC; 110 scm_destroy(scm); 111 return; 112 } 113 114 if (test_bit(SOCK_PASSCRED, &sock->flags)) 115 put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds); 116 117 scm_destroy_cred(scm); 118 119 scm_passec(sock, msg, scm); 120 121 if (!scm->fp) 122 return; 123 124 scm_detach_fds(msg, scm); 125} 126 127 128#endif /* __LINUX_NET_SCM_H */ 129