~ubuntu-branches/ubuntu/trusty/kstart/trusty-proposed

« back to all changes in this revision

Viewing changes to portable/k_haspag.c

  • Committer: Package Import Robot
  • Author(s): Russ Allbery
  • Date: 2012-02-04 18:05:16 UTC
  • mfrom: (1.1.11) (2.1.9 sid)
  • Revision ID: package-import@ubuntu.com-20120204180516-hjeqs2sl3hpvc46p
Tags: 4.1-2
* Update to debhelper compatibility level V9.
  - Enable compiler hardening flags, including bindnow and PIE.
* Move single-debian-patch to local-options and patch-header to
  local-patch-header so that they only apply to the packages I build and
  NMUs get regular version-numbered patches.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Replacement for missing k_haspag kafs function.
 
3
 *
 
4
 * k_haspag is a relatively new addition to the kafs interface (implemented by
 
5
 * Heimdal's libkafs and OpenAFS's libkopenafs).  It returns true if the
 
6
 * current process is in a PAG and false otherwise.  This is a replacement
 
7
 * function for libraries that don't have it or for use with a replacement
 
8
 * kafs layer.  It falls back on looking at the current process's supplemental
 
9
 * groups if the system call isn't supported or if k_pioctl isn't available.
 
10
 *
 
11
 * The canonical version of this file is maintained in the rra-c-util package,
 
12
 * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
 
13
 *
 
14
 * Written by Russ Allbery <rra@stanford.edu>
 
15
 *
 
16
 * The authors hereby relinquish any claim to any copyright that they may have
 
17
 * in this work, whether granted under contract or by operation of law or
 
18
 * international treaty, and hereby commit to the public, at large, that they
 
19
 * shall not, at any time in the future, seek to enforce any copyright in this
 
20
 * work against any person or entity, or prevent any person or entity from
 
21
 * copying, publishing, distributing or creating derivative works of this
 
22
 * work.
 
23
 */
 
24
 
 
25
#include <config.h>
 
26
#include <portable/kafs.h>
 
27
#include <portable/system.h>
 
28
 
 
29
#ifdef HAVE_SYS_IOCCOM_H
 
30
# include <sys/ioccom.h>
 
31
#endif
 
32
#include <sys/ioctl.h>
 
33
 
 
34
 
 
35
/*
 
36
 * The haspag function.  Returns true if the current process is in a PAG,
 
37
 * false otherwise.  This attempts a system call, and if that fails, falls
 
38
 * back on looking for supplemental groups that match the AFS groups.
 
39
 */
 
40
int
 
41
k_haspag(void)
 
42
{
 
43
    int ngroups, i;
 
44
    gid_t *groups;
 
45
    uint32_t pag, g0, g1, hi, lo;
 
46
 
 
47
    /* First, try the system call if k_pioctl is available. */
 
48
#ifdef HAVE_K_PIOCTL
 
49
    int result;
 
50
    struct ViceIoctl iob;
 
51
 
 
52
    iob.in = NULL;
 
53
    iob.in_size = 0;
 
54
    iob.out = (void *) &pag;
 
55
    iob.out_size = sizeof(pag);
 
56
    result = k_pioctl(NULL, _IOW('C', 13, struct ViceIoctl), &iob, 0);
 
57
    if (result == 0)
 
58
        return pag != (uint32_t) -1;
 
59
#endif
 
60
 
 
61
    /*
 
62
     * If that failed, the cache manager may not support the VIOC_GETPAG
 
63
     * system call.  Fall back on analyzing the groups.
 
64
     */
 
65
    ngroups = getgroups(0, NULL);
 
66
    groups = malloc(sizeof(*groups) * ngroups);
 
67
    if (groups == NULL)
 
68
        return 0;
 
69
    ngroups = getgroups(ngroups, groups);
 
70
 
 
71
    /*
 
72
     * Strictly speaking, the single group PAG is only used on Linux, but
 
73
     * check it everywhere anyway to simplify life.
 
74
     */
 
75
    for (i = 0; i < ngroups; i++)
 
76
        if (((groups[i] >> 24) & 0xff) == 'A') {
 
77
            free(groups);
 
78
            return 1;
 
79
        }
 
80
 
 
81
    /*
 
82
     * Check for the PAG group pair.  The first two groups, when combined with
 
83
     * a rather strange formula, must result in a number matching the single
 
84
     * group number we already checked for.
 
85
     */
 
86
    if (ngroups < 2) {
 
87
        free(groups);
 
88
        return 0;
 
89
    }
 
90
    g0 = (groups[0] & 0xffff) - 0x3f00;
 
91
    g1 = (groups[1] & 0xffff) - 0x3f00;
 
92
    free(groups);
 
93
    if (g0 < 0xc0000 && g1 < 0xc0000) {
 
94
        lo = ((g0 & 0x3fff) << 14) | (g1 & 0x3fff);
 
95
        hi = (g1 >> 14) + (g0 >> 14) * 3;
 
96
        pag = ((hi << 28) | lo);
 
97
        return ((pag >> 24) & 0xff) == 'A';
 
98
    }
 
99
    return 0;
 
100
}