1 /* 2 * Copyright (c) 2000 Wichert Akkerman <wakkerma (at) debian.org> 3 * Copyright (c) 2011 Denys Vlasenko <dvlasenk (at) redhat.com> 4 * Copyright (c) 2005-2015 Dmitry V. Levin <ldv (at) altlinux.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include "defs.h" 31 32 /* these constants are the same as in <linux/capability.h> */ 33 enum { 34 #include "caps0.h" 35 }; 36 37 #include "xlat/cap_mask0.h" 38 39 /* these constants are CAP_TO_INDEX'ed constants from <linux/capability.h> */ 40 enum { 41 #include "caps1.h" 42 }; 43 44 #include "xlat/cap_mask1.h" 45 46 /* these constants are the same as in <linux/capability.h> */ 47 enum { 48 _LINUX_CAPABILITY_VERSION_1 = 0x19980330, 49 _LINUX_CAPABILITY_VERSION_2 = 0x20071026, 50 _LINUX_CAPABILITY_VERSION_3 = 0x20080522 51 }; 52 53 #include "xlat/cap_version.h" 54 55 struct user_cap_header_struct { 56 uint32_t version; 57 int pid; 58 }; 59 60 struct user_cap_data_struct { 61 uint32_t effective; 62 uint32_t permitted; 63 uint32_t inheritable; 64 }; 65 66 static const struct user_cap_header_struct * 67 get_cap_header(struct tcb *const tcp, const kernel_ulong_t addr) 68 { 69 static struct user_cap_header_struct header; 70 71 if (!addr || !verbose(tcp)) 72 return NULL; 73 74 if (umove(tcp, addr, &header) < 0) 75 return NULL; 76 77 return &header; 78 } 79 80 static void 81 print_cap_header(struct tcb *const tcp, const kernel_ulong_t addr, 82 const struct user_cap_header_struct *const h) 83 { 84 if (!addr || !h) { 85 printaddr(addr); 86 return; 87 } 88 89 tprints("{version="); 90 printxval(cap_version, h->version, 91 "_LINUX_CAPABILITY_VERSION_???"); 92 tprintf(", pid=%d}", h->pid); 93 } 94 95 static void 96 print_cap_bits(const uint32_t lo, const uint32_t hi) 97 { 98 if (lo || !hi) 99 printflags(cap_mask0, lo, "CAP_???"); 100 101 if (hi) { 102 if (lo) 103 tprints("|"); 104 printflags(cap_mask1, hi, "CAP_???"); 105 } 106 } 107 108 static void 109 print_cap_data(struct tcb *const tcp, const kernel_ulong_t addr, 110 const struct user_cap_header_struct *const h) 111 { 112 struct user_cap_data_struct data[2]; 113 unsigned int len; 114 115 if (!addr || !h) { 116 printaddr(addr); 117 return; 118 } 119 120 if (_LINUX_CAPABILITY_VERSION_2 == h->version || 121 _LINUX_CAPABILITY_VERSION_3 == h->version) 122 len = 2; 123 else 124 len = 1; 125 126 if (umoven_or_printaddr(tcp, addr, len * sizeof(data[0]), data)) 127 return; 128 129 tprints("{effective="); 130 print_cap_bits(data[0].effective, len > 1 ? data[1].effective : 0); 131 tprints(", permitted="); 132 print_cap_bits(data[0].permitted, len > 1 ? data[1].permitted : 0); 133 tprints(", inheritable="); 134 print_cap_bits(data[0].inheritable, len > 1 ? data[1].inheritable : 0); 135 tprints("}"); 136 } 137 138 SYS_FUNC(capget) 139 { 140 const struct user_cap_header_struct *h; 141 142 if (entering(tcp)) { 143 h = get_cap_header(tcp, tcp->u_arg[0]); 144 print_cap_header(tcp, tcp->u_arg[0], h); 145 tprints(", "); 146 } else { 147 h = syserror(tcp) ? NULL : get_cap_header(tcp, tcp->u_arg[0]); 148 print_cap_data(tcp, tcp->u_arg[1], h); 149 } 150 return 0; 151 } 152 153 SYS_FUNC(capset) 154 { 155 const struct user_cap_header_struct *const h = 156 get_cap_header(tcp, tcp->u_arg[0]); 157 print_cap_header(tcp, tcp->u_arg[0], h); 158 tprints(", "); 159 print_cap_data(tcp, tcp->u_arg[1], h); 160 161 return RVAL_DECODED; 162 } 163