~ubuntu-branches/ubuntu/saucy/keyutils/saucy

« back to all changes in this revision

Viewing changes to .pc/0001-memleak-from-realloc.patch/keyutils.c

  • Committer: Package Import Robot
  • Author(s): Luk Claes
  • Date: 2013-04-06 09:38:50 UTC
  • mfrom: (10.2.11 sid)
  • Revision ID: package-import@ubuntu.com-20130406093850-e6xnevgf3za1t4y3
Tags: 1.5.5-7
* Taking over with maintainer's consent.
* Adding watch file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* keyutils.c: key utility library
 
2
 *
 
3
 * Copyright (C) 2005,2011 Red Hat, Inc. All Rights Reserved.
 
4
 * Written by David Howells (dhowells@redhat.com)
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU Lesser General Public License
 
8
 * as published by the Free Software Foundation; either version
 
9
 * 2 of the License, or (at your option) any later version.
 
10
 */
 
11
 
 
12
#include <stdio.h>
 
13
#include <stdlib.h>
 
14
#include <stdint.h>
 
15
#include <stdarg.h>
 
16
#include <string.h>
 
17
#include <unistd.h>
 
18
#include <dlfcn.h>
 
19
#include <sys/uio.h>
 
20
#include <errno.h>
 
21
#include <asm/unistd.h>
 
22
#include "keyutils.h"
 
23
 
 
24
const char keyutils_version_string[] = PKGVERSION;
 
25
const char keyutils_build_string[] = PKGBUILD;
 
26
 
 
27
#ifdef NO_GLIBC_KEYERR
 
28
static int error_inited;
 
29
static void (*libc_perror)(const char *msg);
 
30
static char *(*libc_strerror_r)(int errnum, char *buf, size_t n);
 
31
//static int (*libc_xpg_strerror_r)(int errnum, char *buf, size_t n);
 
32
#define RTLD_NEXT      ((void *) -1L)
 
33
#endif
 
34
 
 
35
#define __weak __attribute__((weak))
 
36
 
 
37
key_serial_t __weak add_key(const char *type,
 
38
                            const char *description,
 
39
                            const void *payload,
 
40
                            size_t plen,
 
41
                            key_serial_t ringid)
 
42
{
 
43
        return syscall(__NR_add_key,
 
44
                       type, description, payload, plen, ringid);
 
45
}
 
46
 
 
47
key_serial_t __weak request_key(const char *type,
 
48
                                const char *description,
 
49
                                const char * callout_info,
 
50
                                key_serial_t destringid)
 
51
{
 
52
        return syscall(__NR_request_key,
 
53
                       type, description, callout_info, destringid);
 
54
}
 
55
 
 
56
static inline long __keyctl(int cmd,
 
57
                            unsigned long arg2,
 
58
                            unsigned long arg3,
 
59
                            unsigned long arg4,
 
60
                            unsigned long arg5)
 
61
{
 
62
        return syscall(__NR_keyctl,
 
63
                       cmd, arg2, arg3, arg4, arg5);
 
64
}
 
65
 
 
66
long __weak keyctl(int cmd, ...)
 
67
{
 
68
        va_list va;
 
69
        unsigned long arg2, arg3, arg4, arg5;
 
70
 
 
71
        va_start(va, cmd);
 
72
        arg2 = va_arg(va, unsigned long);
 
73
        arg3 = va_arg(va, unsigned long);
 
74
        arg4 = va_arg(va, unsigned long);
 
75
        arg5 = va_arg(va, unsigned long);
 
76
        va_end(va);
 
77
 
 
78
        return __keyctl(cmd, arg2, arg3, arg4, arg5);
 
79
}
 
80
 
 
81
key_serial_t keyctl_get_keyring_ID(key_serial_t id, int create)
 
82
{
 
83
        return keyctl(KEYCTL_GET_KEYRING_ID, id, create);
 
84
}
 
85
 
 
86
key_serial_t keyctl_join_session_keyring(const char *name)
 
87
{
 
88
        return keyctl(KEYCTL_JOIN_SESSION_KEYRING, name);
 
89
}
 
90
 
 
91
long keyctl_update(key_serial_t id, const void *payload, size_t plen)
 
92
{
 
93
        return keyctl(KEYCTL_UPDATE, id, payload, plen);
 
94
}
 
95
 
 
96
long keyctl_revoke(key_serial_t id)
 
97
{
 
98
        return keyctl(KEYCTL_REVOKE, id);
 
99
}
 
100
 
 
101
long keyctl_chown(key_serial_t id, uid_t uid, gid_t gid)
 
102
{
 
103
        return keyctl(KEYCTL_CHOWN, id, uid, gid);
 
104
}
 
105
 
 
106
long keyctl_setperm(key_serial_t id, key_perm_t perm)
 
107
{
 
108
        return keyctl(KEYCTL_SETPERM, id, perm);
 
109
}
 
110
 
 
111
long keyctl_describe(key_serial_t id, char *buffer, size_t buflen)
 
112
{
 
113
        return keyctl(KEYCTL_DESCRIBE, id, buffer, buflen);
 
114
}
 
115
 
 
116
long keyctl_clear(key_serial_t ringid)
 
117
{
 
118
        return keyctl(KEYCTL_CLEAR, ringid);
 
119
}
 
120
 
 
121
long keyctl_link(key_serial_t id, key_serial_t ringid)
 
122
{
 
123
        return keyctl(KEYCTL_LINK, id, ringid);
 
124
}
 
125
 
 
126
long keyctl_unlink(key_serial_t id, key_serial_t ringid)
 
127
{
 
128
        return keyctl(KEYCTL_UNLINK, id, ringid);
 
129
}
 
130
 
 
131
long keyctl_search(key_serial_t ringid,
 
132
                   const char *type,
 
133
                   const char *description,
 
134
                   key_serial_t destringid)
 
135
{
 
136
        return keyctl(KEYCTL_SEARCH, ringid, type, description, destringid);
 
137
}
 
138
 
 
139
long keyctl_read(key_serial_t id, char *buffer, size_t buflen)
 
140
{
 
141
        return keyctl(KEYCTL_READ, id, buffer, buflen);
 
142
}
 
143
 
 
144
long keyctl_instantiate(key_serial_t id,
 
145
                        const void *payload,
 
146
                        size_t plen,
 
147
                        key_serial_t ringid)
 
148
{
 
149
        return keyctl(KEYCTL_INSTANTIATE, id, payload, plen, ringid);
 
150
}
 
151
 
 
152
long keyctl_negate(key_serial_t id, unsigned timeout, key_serial_t ringid)
 
153
{
 
154
        return keyctl(KEYCTL_NEGATE, id, timeout, ringid);
 
155
}
 
156
 
 
157
long keyctl_set_reqkey_keyring(int reqkey_defl)
 
158
{
 
159
        return keyctl(KEYCTL_SET_REQKEY_KEYRING, reqkey_defl);
 
160
}
 
161
 
 
162
long keyctl_set_timeout(key_serial_t id, unsigned timeout)
 
163
{
 
164
        return keyctl(KEYCTL_SET_TIMEOUT, id, timeout);
 
165
}
 
166
 
 
167
long keyctl_assume_authority(key_serial_t id)
 
168
{
 
169
        return keyctl(KEYCTL_ASSUME_AUTHORITY, id);
 
170
}
 
171
 
 
172
long keyctl_get_security(key_serial_t id, char *buffer, size_t buflen)
 
173
{
 
174
        return keyctl(KEYCTL_GET_SECURITY, id, buffer, buflen);
 
175
}
 
176
 
 
177
long keyctl_session_to_parent(void)
 
178
{
 
179
        return keyctl(KEYCTL_SESSION_TO_PARENT);
 
180
}
 
181
 
 
182
long keyctl_reject(key_serial_t id, unsigned timeout, unsigned error,
 
183
                   key_serial_t ringid)
 
184
{
 
185
        long ret = keyctl(KEYCTL_REJECT, id, timeout, error, ringid);
 
186
 
 
187
        /* fall back to keyctl_negate() if this op is not supported by this
 
188
         * kernel version */
 
189
        if (ret == -1 && errno == EOPNOTSUPP)
 
190
                return keyctl_negate(id, timeout, ringid);
 
191
        return ret;
 
192
}
 
193
 
 
194
long keyctl_instantiate_iov(key_serial_t id,
 
195
                            const struct iovec *payload_iov,
 
196
                            unsigned ioc,
 
197
                            key_serial_t ringid)
 
198
{
 
199
        long ret = keyctl(KEYCTL_INSTANTIATE_IOV, id, payload_iov, ioc, ringid);
 
200
 
 
201
        /* fall back to keyctl_instantiate() if this op is not supported by
 
202
         * this kernel version */
 
203
        if (ret == -1 && errno == EOPNOTSUPP) {
 
204
                unsigned loop;
 
205
                size_t bsize = 0, seg;
 
206
                void *buf, *p;
 
207
 
 
208
                if (!payload_iov || !ioc)
 
209
                        return keyctl_instantiate(id, NULL, 0, ringid);
 
210
                for (loop = 0; loop < ioc; loop++)
 
211
                        bsize += payload_iov[loop].iov_len;
 
212
                if (bsize == 0)
 
213
                        return keyctl_instantiate(id, NULL, 0, ringid);
 
214
                p = buf = malloc(bsize);
 
215
                if (!buf)
 
216
                        return -1;
 
217
                for (loop = 0; loop < ioc; loop++) {
 
218
                        seg = payload_iov[loop].iov_len;
 
219
                        p = memcpy(p, payload_iov[loop].iov_base, seg) + seg;
 
220
                }
 
221
                ret = keyctl_instantiate(id, buf, bsize, ringid);
 
222
                free(buf);
 
223
        }
 
224
        return ret;
 
225
}
 
226
 
 
227
/*****************************************************************************/
 
228
/*
 
229
 * fetch key description into an allocated buffer
 
230
 * - resulting string is NUL terminated
 
231
 * - returns count not including NUL
 
232
 */
 
233
int keyctl_describe_alloc(key_serial_t id, char **_buffer)
 
234
{
 
235
        char *buf;
 
236
        long buflen, ret;
 
237
 
 
238
        ret = keyctl_describe(id, NULL, 0);
 
239
        if (ret < 0)
 
240
                return -1;
 
241
 
 
242
        buflen = ret;
 
243
        buf = malloc(buflen);
 
244
        if (!buf)
 
245
                return -1;
 
246
 
 
247
        for (;;) {
 
248
                ret = keyctl_describe(id, buf, buflen);
 
249
                if (ret < 0)
 
250
                        return -1;
 
251
 
 
252
                if (buflen >= ret)
 
253
                        break;
 
254
 
 
255
                buflen = ret;
 
256
                buf = realloc(buf, buflen);
 
257
                if (!buf)
 
258
                        return -1;
 
259
        }
 
260
 
 
261
        *_buffer = buf;
 
262
        return buflen - 1;
 
263
 
 
264
} /* end keyctl_describe_alloc() */
 
265
 
 
266
/*****************************************************************************/
 
267
/*
 
268
 * fetch key contents into an allocated buffer
 
269
 * - resulting buffer has an extra NUL added to the end
 
270
 * - returns count (not including extraneous NUL)
 
271
 */
 
272
int keyctl_read_alloc(key_serial_t id, void **_buffer)
 
273
{
 
274
        void *buf;
 
275
        long buflen, ret;
 
276
 
 
277
        ret = keyctl_read(id, NULL, 0);
 
278
        if (ret < 0)
 
279
                return -1;
 
280
 
 
281
        buflen = ret;
 
282
        buf = malloc(buflen + 1);
 
283
        if (!buf)
 
284
                return -1;
 
285
 
 
286
        for (;;) {
 
287
                ret = keyctl_read(id, buf, buflen);
 
288
                if (ret < 0)
 
289
                        return -1;
 
290
 
 
291
                if (buflen >= ret)
 
292
                        break;
 
293
 
 
294
                buflen = ret;
 
295
                buf = realloc(buf, buflen + 1);
 
296
                if (!buf)
 
297
                        return -1;
 
298
        }
 
299
 
 
300
        ((unsigned char *) buf)[buflen] = 0;
 
301
        *_buffer = buf;
 
302
        return buflen;
 
303
 
 
304
} /* end keyctl_read_alloc() */
 
305
 
 
306
/*****************************************************************************/
 
307
/*
 
308
 * fetch key security label into an allocated buffer
 
309
 * - resulting string is NUL terminated
 
310
 * - returns count not including NUL
 
311
 */
 
312
int keyctl_get_security_alloc(key_serial_t id, char **_buffer)
 
313
{
 
314
        char *buf;
 
315
        long buflen, ret;
 
316
 
 
317
        ret = keyctl_get_security(id, NULL, 0);
 
318
        if (ret < 0)
 
319
                return -1;
 
320
 
 
321
        buflen = ret;
 
322
        buf = malloc(buflen);
 
323
        if (!buf)
 
324
                return -1;
 
325
 
 
326
        for (;;) {
 
327
                ret = keyctl_get_security(id, buf, buflen);
 
328
                if (ret < 0)
 
329
                        return -1;
 
330
 
 
331
                if (buflen >= ret)
 
332
                        break;
 
333
 
 
334
                buflen = ret;
 
335
                buf = realloc(buf, buflen);
 
336
                if (!buf)
 
337
                        return -1;
 
338
        }
 
339
 
 
340
        *_buffer = buf;
 
341
        return buflen - 1;
 
342
}
 
343
 
 
344
/*
 
345
 * Depth-first recursively apply a function over a keyring tree
 
346
 */
 
347
static int recursive_key_scan_aux(key_serial_t parent, key_serial_t key,
 
348
                                  int depth, recursive_key_scanner_t func,
 
349
                                  void *data)
 
350
{
 
351
        key_serial_t *pk;
 
352
        key_perm_t perm;
 
353
        size_t ringlen;
 
354
        void *ring;
 
355
        char *desc, type[255];
 
356
        int desc_len, uid, gid, ret, n, kcount = 0;
 
357
 
 
358
        if (depth > 800)
 
359
                return 0;
 
360
 
 
361
        /* read the key description */
 
362
        desc = NULL;
 
363
        desc_len = keyctl_describe_alloc(key, &desc);
 
364
        if (desc_len < 0)
 
365
                goto do_this_key;
 
366
 
 
367
        /* parse */
 
368
        type[0] = 0;
 
369
 
 
370
        n = sscanf(desc, "%[^;];%d;%d;%x;", type, &uid, &gid, &perm);
 
371
        if (n != 4) {
 
372
                free(desc);
 
373
                desc = NULL;
 
374
                errno = -EINVAL;
 
375
                desc_len = -1;
 
376
                goto do_this_key;
 
377
        }
 
378
 
 
379
        /* if it's a keyring then we're going to want to recursively search it
 
380
         * if we can */
 
381
        if (strcmp(type, "keyring") == 0) {
 
382
                /* read the keyring's contents */
 
383
                ret = keyctl_read_alloc(key, &ring);
 
384
                if (ret < 0)
 
385
                        goto do_this_key;
 
386
 
 
387
                ringlen = ret;
 
388
 
 
389
                /* walk the keyring */
 
390
                pk = ring;
 
391
                for (ringlen = ret;
 
392
                     ringlen >= sizeof(key_serial_t);
 
393
                     ringlen -= sizeof(key_serial_t)
 
394
                     )
 
395
                        kcount += recursive_key_scan_aux(key, *pk++, depth + 1,
 
396
                                                         func, data);
 
397
 
 
398
                free(ring);
 
399
        }
 
400
 
 
401
do_this_key:
 
402
        kcount += func(parent, key, desc, desc_len, data);
 
403
        free(desc);
 
404
        return kcount;
 
405
}
 
406
 
 
407
/*
 
408
 * Depth-first apply a function over a keyring tree
 
409
 */
 
410
int recursive_key_scan(key_serial_t key, recursive_key_scanner_t func, void *data)
 
411
{
 
412
        return recursive_key_scan_aux(0, key, 0, func, data);
 
413
}
 
414
 
 
415
/*
 
416
 * Depth-first apply a function over session keyring tree
 
417
 */
 
418
int recursive_session_key_scan(recursive_key_scanner_t func, void *data)
 
419
{
 
420
        key_serial_t session =
 
421
                keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 0);
 
422
        if (session > 0)
 
423
                return recursive_key_scan(session, func, data);
 
424
        return 0;
 
425
}
 
426
 
 
427
#ifdef NO_GLIBC_KEYERR
 
428
/*****************************************************************************/
 
429
/*
 
430
 * initialise error handling
 
431
 */
 
432
static void error_init(void)
 
433
{
 
434
        char *err;
 
435
 
 
436
        error_inited = 1;
 
437
 
 
438
        dlerror();
 
439
 
 
440
        libc_perror = dlsym(RTLD_NEXT,"perror");
 
441
        if (!libc_perror) {
 
442
                fprintf(stderr, "Failed to look up next perror\n");
 
443
                err = dlerror();
 
444
                if (err)
 
445
                        fprintf(stderr, "%s\n", err);
 
446
                abort();
 
447
        }
 
448
 
 
449
        //fprintf(stderr, "next perror at %p\n", libc_perror);
 
450
 
 
451
        libc_strerror_r = dlsym(RTLD_NEXT,"strerror_r");
 
452
        if (!libc_strerror_r) {
 
453
                fprintf(stderr, "Failed to look up next strerror_r\n");
 
454
                err = dlerror();
 
455
                if (err)
 
456
                        fprintf(stderr, "%s\n", err);
 
457
                abort();
 
458
        }
 
459
 
 
460
        //fprintf(stderr, "next strerror_r at %p\n", libc_strerror_r);
 
461
 
 
462
#if 0
 
463
        libc_xpg_strerror_r = dlsym(RTLD_NEXT,"xpg_strerror_r");
 
464
        if (!libc_xpg_strerror_r) {
 
465
                fprintf(stderr, "Failed to look up next xpg_strerror_r\n");
 
466
                err = dlerror();
 
467
                if (err)
 
468
                        fprintf(stderr, "%s\n", err);
 
469
                abort();
 
470
        }
 
471
 
 
472
        //fprintf(stderr, "next xpg_strerror_r at %p\n", libc_xpg_strerror_r);
 
473
#endif
 
474
 
 
475
} /* end error_init() */
 
476
 
 
477
/*****************************************************************************/
 
478
/*
 
479
 * overload glibc's strerror_r() with a version that knows about key errors
 
480
 */
 
481
char *strerror_r(int errnum, char *buf, size_t n)
 
482
{
 
483
        const char *errstr;
 
484
        int len;
 
485
 
 
486
        printf("hello\n");
 
487
 
 
488
        if (!error_inited)
 
489
                error_init();
 
490
 
 
491
        switch (errnum) {
 
492
        case ENOKEY:
 
493
                errstr = "Requested key not available";
 
494
                break;
 
495
 
 
496
        case EKEYEXPIRED:
 
497
                errstr = "Key has expired";
 
498
                break;
 
499
 
 
500
        case EKEYREVOKED:
 
501
                errstr = "Key has been revoked";
 
502
                break;
 
503
 
 
504
        case EKEYREJECTED:
 
505
                errstr = "Key was rejected by service";
 
506
                break;
 
507
 
 
508
        default:
 
509
                return libc_strerror_r(errnum, buf, n);
 
510
        }
 
511
 
 
512
        len = strlen(errstr) + 1;
 
513
        if (n > len) {
 
514
                errno = ERANGE;
 
515
                if (n > 0) {
 
516
                        memcpy(buf, errstr, n - 1);
 
517
                        buf[n - 1] = 0;
 
518
                }
 
519
                return NULL;
 
520
        }
 
521
        else {
 
522
                memcpy(buf, errstr, len);
 
523
                return buf;
 
524
        }
 
525
 
 
526
} /* end strerror_r() */
 
527
 
 
528
#if 0
 
529
/*****************************************************************************/
 
530
/*
 
531
 * overload glibc's strerror_r() with a version that knows about key errors
 
532
 */
 
533
int xpg_strerror_r(int errnum, char *buf, size_t n)
 
534
{
 
535
        const char *errstr;
 
536
        int len;
 
537
 
 
538
        if (!error_inited)
 
539
                error_init();
 
540
 
 
541
        switch (errnum) {
 
542
        case ENOKEY:
 
543
                errstr = "Requested key not available";
 
544
                break;
 
545
 
 
546
        case EKEYEXPIRED:
 
547
                errstr = "Key has expired";
 
548
                break;
 
549
 
 
550
        case EKEYREVOKED:
 
551
                errstr = "Key has been revoked";
 
552
                break;
 
553
 
 
554
        case EKEYREJECTED:
 
555
                errstr = "Key was rejected by service";
 
556
                break;
 
557
 
 
558
        default:
 
559
                return libc_xpg_strerror_r(errnum, buf, n);
 
560
        }
 
561
 
 
562
        len = strlen(errstr) + 1;
 
563
        if (n > len) {
 
564
                errno = ERANGE;
 
565
                if (n > 0) {
 
566
                        memcpy(buf, errstr, n - 1);
 
567
                        buf[n - 1] = 0;
 
568
                }
 
569
                return -1;
 
570
        }
 
571
        else {
 
572
                memcpy(buf, errstr, len);
 
573
                return 0;
 
574
        }
 
575
 
 
576
} /* end xpg_strerror_r() */
 
577
#endif
 
578
 
 
579
/*****************************************************************************/
 
580
/*
 
581
 *
 
582
 */
 
583
void perror(const char *msg)
 
584
{
 
585
        if (!error_inited)
 
586
                error_init();
 
587
 
 
588
        switch (errno) {
 
589
        case ENOKEY:
 
590
                fprintf(stderr, "%s: Requested key not available\n", msg);
 
591
                return;
 
592
 
 
593
        case EKEYEXPIRED:
 
594
                fprintf(stderr, "%s: Key has expired\n", msg);
 
595
                return;
 
596
 
 
597
        case EKEYREVOKED:
 
598
                fprintf(stderr, "%s: Key has been revoked\n", msg);
 
599
                return;
 
600
 
 
601
        case EKEYREJECTED:
 
602
                fprintf(stderr, "%s: Key was rejected by service\n", msg);
 
603
                return;
 
604
 
 
605
        default:
 
606
                libc_perror(msg);
 
607
                return;
 
608
        }
 
609
 
 
610
} /* end perror() */
 
611
#endif