libexplain  1.4.D001
libexplain/buffer/eacces/shm.c
Go to the documentation of this file.
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 : */