(root)/
strace-6.5/
src/
capability.c
       1  /*
       2   * Copyright (c) 2000 Wichert Akkerman <wakkerma@debian.org>
       3   * Copyright (c) 2011 Denys Vlasenko <dvlasenk@redhat.com>
       4   * Copyright (c) 2005-2015 Dmitry V. Levin <ldv@strace.io>
       5   * Copyright (c) 2014-2022 The strace developers.
       6   * All rights reserved.
       7   *
       8   * SPDX-License-Identifier: LGPL-2.1-or-later
       9   */
      10  
      11  #include "defs.h"
      12  
      13  /* these constants are the same as in <linux/capability.h> */
      14  enum {
      15  #include "caps0.h"
      16  };
      17  
      18  #include "xlat/cap_mask0.h"
      19  
      20  /* these constants are CAP_TO_INDEX'ed constants from <linux/capability.h> */
      21  enum {
      22  #include "caps1.h"
      23  };
      24  
      25  #include "xlat/cap_mask1.h"
      26  
      27  /* these constants are the same as in <linux/capability.h> */
      28  enum {
      29  	_LINUX_CAPABILITY_VERSION_1 = 0x19980330,
      30  	_LINUX_CAPABILITY_VERSION_2 = 0x20071026,
      31  	_LINUX_CAPABILITY_VERSION_3 = 0x20080522
      32  };
      33  
      34  #include "xlat/cap_version.h"
      35  
      36  struct user_cap_header_struct {
      37  	uint32_t version;
      38  	int pid;
      39  };
      40  
      41  struct user_cap_data_struct {
      42  	uint32_t effective;
      43  	uint32_t permitted;
      44  	uint32_t inheritable;
      45  };
      46  
      47  static const struct user_cap_header_struct *
      48  get_cap_header(struct tcb *const tcp, const kernel_ulong_t addr)
      49  {
      50  	static struct user_cap_header_struct header;
      51  
      52  	if (!addr || !verbose(tcp))
      53  		return NULL;
      54  
      55  	if (umove(tcp, addr, &header) < 0)
      56  		return NULL;
      57  
      58  	return &header;
      59  }
      60  
      61  static void
      62  print_cap_header(struct tcb *const tcp, const kernel_ulong_t addr,
      63  		 const struct user_cap_header_struct *const h)
      64  {
      65  	if (!addr || !h) {
      66  		printaddr(addr);
      67  		return;
      68  	}
      69  
      70  	tprint_struct_begin();
      71  	PRINT_FIELD_XVAL(*h, version, cap_version,
      72  			 "_LINUX_CAPABILITY_VERSION_???");
      73  	tprint_struct_next();
      74  	PRINT_FIELD_TGID(*h, pid, tcp);
      75  	tprint_struct_end();
      76  }
      77  
      78  static void
      79  print_cap_bits(const uint32_t lo, const uint32_t hi)
      80  {
      81  	tprint_flags_begin();
      82  	if (lo || !hi)
      83  		printflags_in(cap_mask0, lo, "CAP_???");
      84  
      85  	if (hi) {
      86  		if (lo)
      87  			tprint_flags_or();
      88  		printflags_in(cap_mask1, hi, "CAP_???");
      89  	}
      90  	tprint_flags_end();
      91  }
      92  
      93  static void
      94  print_cap_data(struct tcb *const tcp, const kernel_ulong_t addr,
      95  	       const struct user_cap_header_struct *const h)
      96  {
      97  	struct user_cap_data_struct data[2];
      98  	unsigned int len;
      99  
     100  	if (!addr || !h) {
     101  		printaddr(addr);
     102  		return;
     103  	}
     104  
     105  	if (_LINUX_CAPABILITY_VERSION_2 == h->version ||
     106  	    _LINUX_CAPABILITY_VERSION_3 == h->version)
     107  		len = 2;
     108  	else
     109  		len = 1;
     110  
     111  	if (umoven_or_printaddr(tcp, addr, len * sizeof(data[0]), data))
     112  		return;
     113  
     114  	tprint_struct_begin();
     115  	tprints_field_name("effective");
     116  	print_cap_bits(data[0].effective, len > 1 ? data[1].effective : 0);
     117  	tprint_struct_next();
     118  	tprints_field_name("permitted");
     119  	print_cap_bits(data[0].permitted, len > 1 ? data[1].permitted : 0);
     120  	tprint_struct_next();
     121  	tprints_field_name("inheritable");
     122  	print_cap_bits(data[0].inheritable, len > 1 ? data[1].inheritable : 0);
     123  	tprint_struct_end();
     124  }
     125  
     126  SYS_FUNC(capget)
     127  {
     128  	const struct user_cap_header_struct *h;
     129  
     130  	if (entering(tcp)) {
     131  		/* hdrp */
     132  		h = get_cap_header(tcp, tcp->u_arg[0]);
     133  		print_cap_header(tcp, tcp->u_arg[0], h);
     134  		tprint_arg_next();
     135  	} else {
     136  		/* datap */
     137  		h = syserror(tcp) ? NULL : get_cap_header(tcp, tcp->u_arg[0]);
     138  		print_cap_data(tcp, tcp->u_arg[1], h);
     139  	}
     140  	return 0;
     141  }
     142  
     143  SYS_FUNC(capset)
     144  {
     145  	/* hdrp */
     146  	const struct user_cap_header_struct *const h =
     147  		get_cap_header(tcp, tcp->u_arg[0]);
     148  	print_cap_header(tcp, tcp->u_arg[0], h);
     149  	tprint_arg_next();
     150  
     151  	/* datap */
     152  	print_cap_data(tcp, tcp->u_arg[1], h);
     153  
     154  	return RVAL_DECODED;
     155  }