LCOV - code coverage report
Current view: top level - include/net - scm.h (source / functions) Hit Total Coverage
Test: landlock.info Lines: 44 44 100.0 %
Date: 2021-04-22 12:43:58 Functions: 4 4 100.0 %

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

Generated by: LCOV version 1.14