libexplain
1.4.D001
|
00001 /* 00002 * libexplain - a library of system-call-specific strerror replacements 00003 * Copyright (C) 2011, 2013 Peter Miller 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU Lesser General Public License as 00007 * published by the Free Software Foundation; either version 3 of the 00008 * License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Lesser General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public License 00016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00017 */ 00018 00019 #include <libexplain/ac/sys/shm.h> 00020 #include <libexplain/ac/sys/stat.h> 00021 #include <libexplain/ac/unistd.h> 00022 00023 #include <libexplain/buffer/dac.h> 00024 #include <libexplain/buffer/eacces.h> 00025 #include <libexplain/buffer/gettext.h> 00026 #include <libexplain/buffer/gid.h> 00027 #include <libexplain/buffer/group_permission_ignored.h> 00028 #include <libexplain/buffer/others_permission.h> 00029 #include <libexplain/buffer/others_permission_ignored.h> 00030 #include <libexplain/buffer/rwx.h> 00031 #include <libexplain/buffer/uid.h> 00032 #include <libexplain/capability.h> 00033 #include <libexplain/gettext.h> 00034 #include <libexplain/option.h> 00035 #include <libexplain/translate.h> 00036 00037 00038 static void 00039 owner_permission_mode_used(explain_string_buffer_t *sb, 00040 const struct ipc_perm *perm, uid_t proc_uid, const char *proc_uid_caption, 00041 const char *whatsit, const char *ipc_uid_caption) 00042 { 00043 char part2[40]; 00044 explain_string_buffer_t part2_sb; 00045 char part4[8]; 00046 explain_string_buffer_t part4_sb; 00047 00048 explain_string_buffer_init(&part2_sb, part2, sizeof(part2)); 00049 explain_buffer_uid(&part2_sb, proc_uid); 00050 explain_string_buffer_init(&part4_sb, part4, sizeof(part4)); 00051 explain_buffer_rwx(&part4_sb, perm->mode & S_IRWXU); 00052 00053 explain_string_buffer_puts(sb, ", "); 00054 explain_string_buffer_printf_gettext 00055 ( 00056 sb, 00057 /* 00058 * xgettext: This message is used when explaining which permission mode 00059 * bits are used when determining IPC access permissions. 00060 * 00061 * %1$s => the kind of process UID, "real UID" or "effective UID", 00062 * already translated. 00063 * %2$s => the UID of the process, number and name. 00064 * %3$s => the kind if IPC object, e.g. "shared memory segment", 00065 * already translated 00066 * %4$s => the kind of IPC object UID, "owner UID" or 00067 * "creator UID", already translated. 00068 * %5$s => The mode bits like "rwx", including the quotes, in 00069 * a form resembling the ls -l representation of mode 00070 * bits. 00071 */ 00072 i18n("the process %s %s matches the %s %s and the " 00073 "owner permission mode is %s"), 00074 proc_uid_caption, 00075 part2, 00076 whatsit, 00077 ipc_uid_caption, 00078 part4 00079 ); 00080 } 00081 00082 00083 static void 00084 owner_permission_mode_mismatch(explain_string_buffer_t *sb, 00085 const struct ipc_perm *perm, int proc_uid, const char *proc_uid_caption, 00086 const char *whatsit, int shm_uid, const char *shm_uid_caption) 00087 { 00088 char part1[40]; 00089 explain_string_buffer_t part1_sb; 00090 char part2[40]; 00091 explain_string_buffer_t part2_sb; 00092 char part3[8]; 00093 explain_string_buffer_t part3_sb; 00094 00095 explain_string_buffer_init(&part1_sb, part1, sizeof(part1)); 00096 explain_buffer_uid(&part1_sb, proc_uid); 00097 explain_string_buffer_init(&part2_sb, part2, sizeof(part2)); 00098 explain_buffer_uid(&part2_sb, shm_uid); 00099 explain_string_buffer_init(&part3_sb, part3, sizeof(part3)); 00100 explain_buffer_rwx(&part3_sb, perm->mode & S_IRWXU); 00101 00102 explain_string_buffer_puts(sb, ", "); 00103 explain_string_buffer_printf_gettext 00104 ( 00105 sb, 00106 /* 00107 * xgettext: This message is used when explaining which owner permission 00108 * mode bits are ignored when determining IPC access permissions. 00109 * 00110 * %1$s => the kind of process UID, "real UID" or "effective UID", 00111 * already translated 00112 * %2$s => the UID of the process, number and name. 00113 * %3$s => the kind of IPC object, e.g. "shared memory segment", 00114 * already tramslated 00115 * %4$s => the kind of shm UID, "owner UID" or "creator UID" 00116 * %5$s => the shm UID of the IPC object, number and name. 00117 * %6$s => The mode bits like "rwx", including the quotes, in 00118 * a form resembling the ls -l representation of mode 00119 * bits. 00120 */ 00121 i18n("the process %s %s does not match the %s %s %s " 00122 "so the owner permission mode %s is ignored"), 00123 proc_uid_caption, 00124 part1, 00125 whatsit, 00126 shm_uid_caption, 00127 part2, 00128 part3 00129 ); 00130 } 00131 00132 00133 static void 00134 group_permission_mode_used(explain_string_buffer_t *sb, 00135 const struct ipc_perm *perm, int proc_gid, const char *proc_gid_caption, 00136 const char *whatsit, const char *ipc_gid_caption) 00137 { 00138 char part1[40]; 00139 explain_string_buffer_t part1_sb; 00140 char part3[8]; 00141 explain_string_buffer_t part3_sb; 00142 00143 explain_string_buffer_init(&part1_sb, part1, sizeof(part1)); 00144 explain_buffer_gid(&part1_sb, proc_gid); 00145 explain_string_buffer_init(&part3_sb, part3, sizeof(part3)); 00146 explain_buffer_rwx(&part3_sb, perm->mode & S_IRWXG); 00147 00148 explain_string_buffer_puts(sb, ", "); 00149 explain_string_buffer_printf_gettext 00150 ( 00151 sb, 00152 /* 00153 * xgettext: This message is used when explaining which permission 00154 * mode bits are used when determining IPC access permissions. 00155 * 00156 * This is explicitly nothing to do with files. 00157 * 00158 * %1$s => the process kind of GID, "real GID" or "effective GID", 00159 * already translated 00160 * %2$s => the GID of the process, number and name. 00161 * %3$s => the kinf of IPC object, e.g. "shared memory segment", 00162 * already translated 00163 * %4$s => the IPC object kind of GID, "owner GID" or "creator GID", 00164 * already translated 00165 * %5$s => the GID of the IPC object, number and name. 00166 * %6$s => The mode bits like "rwx", including the quotes, in 00167 * a form resembling the ls -l representation of mode 00168 * bits. 00169 */ 00170 i18n("the process %s %s matches the %s %s and " 00171 "the group permission mode is %s"), 00172 proc_gid_caption, 00173 part1, 00174 whatsit, 00175 ipc_gid_caption, 00176 part3 00177 ); 00178 } 00179 00180 00181 static void 00182 group_permission_mode_mismatch(explain_string_buffer_t *sb, 00183 const struct ipc_perm *perm, int proc_gid, const char *proc_gid_caption, 00184 const char *whatsit, int ipc_gid, const char *ipc_gid_caption) 00185 { 00186 char part1[40]; 00187 explain_string_buffer_t part1_sb; 00188 char part2[40]; 00189 explain_string_buffer_t part2_sb; 00190 char part3[8]; 00191 explain_string_buffer_t part3_sb; 00192 00193 explain_string_buffer_init(&part1_sb, part1, sizeof(part1)); 00194 explain_buffer_gid(&part1_sb, proc_gid); 00195 explain_string_buffer_init(&part2_sb, part2, sizeof(part2)); 00196 explain_buffer_gid(&part2_sb, ipc_gid); 00197 explain_string_buffer_init(&part3_sb, part3, sizeof(part3)); 00198 explain_buffer_rwx(&part3_sb, perm->mode & S_IRWXG); 00199 00200 explain_string_buffer_puts(sb, ", "); 00201 explain_string_buffer_printf_gettext 00202 ( 00203 sb, 00204 /* 00205 * xgettext: This message is used when explaining which permission 00206 * mode bits are used when determining IPC access permissions. 00207 * 00208 * This is explicitly nothing to do with files. 00209 * 00210 * %1$s => the process kind of GID, "real GID" or "effective GID", 00211 * already translated 00212 * %2$s => the GID of the process, number and name. 00213 * %3$s => the IPOC onject kind, e.g. "shared memory segment", 00214 * already trsmalated 00215 * %4$s => the IPC object kind of GID, "owner GID" or "creator GID", 00216 * already translated 00217 * %5$s => the GID of the IPC object, number and name. 00218 * %6$s => The mode bits like "rwx", including the quotes, in 00219 * a form resembling the ls -l representation of mode 00220 * bits. 00221 */ 00222 i18n("the process %s %s does not match the %s %s %s " 00223 "and so the group permission mode %s is ignored"), 00224 proc_gid_caption, 00225 part1, 00226 whatsit, 00227 ipc_gid_caption, 00228 part2, 00229 part3 00230 ); 00231 } 00232 00233 00234 static const char * 00235 translate_owner_uid(void) 00236 { 00237 return 00238 explain_gettext 00239 ( 00240 /* 00241 * xgettext: this phrase it used to describe an aspect of IPC 00242 * object, the owner user id (see struct ipc_perm member uid, or 00243 * shmat(2) for more information). 00244 * 00245 * This is explicitly nothing to do with files. 00246 */ 00247 i18n("owner UID") 00248 ); 00249 } 00250 00251 00252 static const char * 00253 translate_creator_uid(void) 00254 { 00255 return 00256 explain_gettext 00257 ( 00258 /* 00259 * xgettext: this phrase it used to describe an aspect of IPC 00260 * object, the creator user id (see struct ipc_perm member cuid, or 00261 * shmat(2) for more information). 00262 * 00263 * This is explicitly nothing to do with files. 00264 */ 00265 i18n("creator UID") 00266 ); 00267 } 00268 00269 00270 static const char * 00271 translate_owner_gid(void) 00272 { 00273 return 00274 explain_gettext 00275 ( 00276 /* 00277 * xgettext: this phrase it used to describe an aspect of 00278 * IPC object, their owner group id (see ipc_perm::gid, or 00279 * shmat(2) for more information). 00280 * 00281 * This is explicitly nothing to do with files. 00282 */ 00283 i18n("owner GID") 00284 ); 00285 } 00286 00287 00288 static const char * 00289 translate_creator_gid(void) 00290 { 00291 return 00292 explain_gettext 00293 ( 00294 /* 00295 * xgettext: this phrase it used to describe an aspect of 00296 * IPC object, their creator group id (see ipc_perm::cgid, or 00297 * shmat(2) for more information). 00298 * 00299 * This is explicitly nothing to do with files. 00300 */ 00301 i18n("creator GID") 00302 ); 00303 } 00304 00305 00306 static void 00307 no_ipc_permission(explain_string_buffer_t *sb, const char *whatsit) 00308 { 00309 explain_string_buffer_printf_gettext 00310 ( 00311 sb, 00312 /* 00313 * xgettext: This error message is used to explain that a 00314 * process does not have the necessary IPC permissions to access 00315 * the resource it requested. 00316 * 00317 * %1$s => The kind of resource, e.g. "shared memory segment" or 00318 * "semaphore", etc. Already translated. 00319 * 00320 */ 00321 i18n("the process does not have the necessary %s access permissions"), 00322 whatsit 00323 ); 00324 } 00325 00326 00327 static int 00328 buffer_eacces_shm(explain_string_buffer_t *sb, const struct ipc_perm *perm, 00329 int read_only, const char *whatsit) 00330 { 00331 uid_t proc_uid; 00332 const char *proc_uid_caption; 00333 gid_t proc_gid; 00334 const char *proc_gid_caption; 00335 uid_t ipc_uid; 00336 const char *ipc_uid_caption; 00337 gid_t ipc_gid; 00338 const char *ipc_gid_caption; 00339 unsigned mode; 00340 00341 mode = read_only ? 0444 : 0666; 00342 00343 if (getuid() == perm->uid) 00344 { 00345 proc_uid = getuid(); 00346 proc_uid_caption = explain_translate_real_uid(); 00347 ipc_uid = perm->uid; 00348 ipc_uid_caption = translate_owner_uid(); 00349 } 00350 else if (getuid() == perm->cuid) 00351 { 00352 proc_uid = getuid(); 00353 proc_uid_caption = explain_translate_real_uid(); 00354 ipc_uid = perm->cuid; 00355 ipc_uid_caption = translate_creator_uid(); 00356 } 00357 else if (geteuid() == perm->uid) 00358 { 00359 proc_uid = geteuid(); 00360 proc_uid_caption = explain_translate_effective_uid(); 00361 ipc_uid = perm->uid; 00362 ipc_uid_caption = translate_owner_uid(); 00363 } 00364 else if (geteuid() == perm->cuid) 00365 { 00366 proc_uid = geteuid(); 00367 proc_uid_caption = explain_translate_effective_uid(); 00368 ipc_uid = perm->cuid; 00369 ipc_uid_caption = translate_creator_uid(); 00370 } 00371 else 00372 { 00373 proc_uid = geteuid(); 00374 proc_uid_caption = explain_translate_effective_uid(); 00375 ipc_uid = perm->uid; 00376 ipc_uid_caption = translate_owner_uid(); 00377 } 00378 00379 if (getgid() == perm->gid) 00380 { 00381 proc_gid = getgid(); 00382 proc_gid_caption = explain_translate_real_gid(); 00383 ipc_gid = perm->gid; 00384 ipc_gid_caption = translate_owner_gid(); 00385 } 00386 else if (getgid() == perm->cgid) 00387 { 00388 proc_gid = getgid(); 00389 proc_gid_caption = explain_translate_real_gid(); 00390 ipc_gid = perm->cgid; 00391 ipc_gid_caption = translate_creator_gid(); 00392 } 00393 else if (getegid() == perm->gid) 00394 { 00395 proc_gid = getegid(); 00396 proc_gid_caption = explain_translate_effective_gid(); 00397 ipc_gid = perm->gid; 00398 ipc_gid_caption = translate_owner_gid(); 00399 } 00400 else if (getegid() == perm->cgid) 00401 { 00402 proc_gid = getegid(); 00403 proc_gid_caption = explain_translate_effective_gid(); 00404 ipc_gid = perm->cgid; 00405 ipc_gid_caption = translate_creator_gid(); 00406 } 00407 else 00408 { 00409 proc_gid = getegid(); 00410 proc_gid_caption = explain_translate_effective_gid(); 00411 ipc_gid = perm->gid; 00412 ipc_gid_caption = translate_owner_gid(); 00413 } 00414 00415 /* 00416 * First, see if there is a permissions problem at all. 00417 */ 00418 if (explain_capability_ipc_owner()) 00419 return 0; 00420 if (proc_uid == ipc_uid) 00421 { 00422 int mode2 = mode & S_IRWXU; 00423 if ((perm->mode & mode2) == mode2) 00424 return 0; 00425 } 00426 else if (proc_gid == ipc_gid) 00427 { 00428 int mode2 = mode & S_IRWXG; 00429 if ((perm->mode & mode2) == mode2) 00430 return 0; 00431 } 00432 else 00433 { 00434 int mode2 = mode & S_IRWXO; 00435 if ((perm->mode & mode2) == mode2) 00436 return 0; 00437 } 00438 00439 /* 00440 * At this point we know something broke. 00441 */ 00442 no_ipc_permission(sb, whatsit); 00443 if (explain_option_dialect_specific()) 00444 { 00445 if (proc_uid == ipc_uid) 00446 { 00447 owner_permission_mode_used(sb, perm, proc_uid, proc_uid_caption, 00448 whatsit, ipc_uid_caption); 00449 explain_buffer_group_permission_ignored(sb, perm->mode); 00450 explain_buffer_others_permission_ignored(sb, perm->mode); 00451 } 00452 else 00453 { 00454 owner_permission_mode_mismatch 00455 ( 00456 sb, 00457 perm, 00458 proc_uid, 00459 proc_uid_caption, 00460 whatsit, 00461 ipc_uid, 00462 ipc_uid_caption 00463 ); 00464 if (proc_gid == ipc_gid) 00465 { 00466 group_permission_mode_used 00467 ( 00468 sb, 00469 perm, 00470 proc_gid, 00471 proc_gid_caption, 00472 whatsit, 00473 ipc_gid_caption 00474 ); 00475 explain_buffer_others_permission_ignored(sb, perm->mode); 00476 } 00477 else 00478 { 00479 group_permission_mode_mismatch 00480 ( 00481 sb, 00482 perm, 00483 proc_gid, 00484 proc_gid_caption, 00485 whatsit, 00486 ipc_gid, 00487 ipc_gid_caption 00488 ); 00489 explain_buffer_others_permission(sb, perm->mode); 00490 } 00491 } 00492 } 00493 explain_buffer_dac_ipc_owner(sb); 00494 00495 /* 00496 * The return value says we printed an explanation. 00497 */ 00498 return 1; 00499 } 00500 00501 00502 int 00503 explain_buffer_eacces_shmat(explain_string_buffer_t *sb, 00504 const struct ipc_perm *perm, int read_only) 00505 { 00506 return 00507 buffer_eacces_shm 00508 ( 00509 sb, 00510 perm, 00511 read_only, 00512 explain_translate_shared_memory_segment() 00513 ); 00514 } 00515 00516 00517 void 00518 explain_buffer_eacces_shmat_vague(explain_string_buffer_t *sb) 00519 { 00520 no_ipc_permission(sb, explain_translate_shared_memory_segment()); 00521 explain_buffer_dac_ipc_owner(sb); 00522 } 00523 00524 00525 /* vim: set ts=8 sw=4 et : */