Home | History | Annotate | Download | only in shm_open
      1 /*
      2  *  This program is free software; you can redistribute it and/or modify
      3  *  it under the terms of the GNU General Public License version 2.
      4  *
      5  *  This program is distributed in the hope that it will be useful,
      6  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      7  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      8  *  GNU General Public License for more details.
      9  *
     10  * Test that the owner is unchanged when O_TRUNC is set, the shared memory
     11  * object exists and it is successfully opened O_RDWR.
     12  *
     13  * In most case this test will be unresolved if not run by root.
     14  * Steps:
     15  *  1. Create a shared memory object.
     16  *  2. Set a non zero size for this object (to force the modification of the
     17  *     object when it will be reopen with O_TRUNC set).
     18  *  3. Set his effective user id to an other user id which is not root.
     19  *  4. Call shm_open with O_TRUNC set.
     20  *  5. Check that the owner is unchanged.
     21  */
     22 
     23 /* getpwent() is part of XSI option */
     24 #define _XOPEN_SOURCE 600
     25 
     26 #include <sys/mman.h>
     27 #include <sys/stat.h>
     28 #include <fcntl.h>
     29 #include <pwd.h>
     30 #include <unistd.h>
     31 #include <errno.h>
     32 #include <string.h>
     33 #include <stdio.h>
     34 #include "posixtest.h"
     35 
     36 #define BUF_SIZE 8
     37 #define SHM_NAME "posixtest_26-2"
     38 
     39 int main(void)
     40 {
     41 	int fd;
     42 	struct stat stat_buf;
     43 	struct passwd *pw;
     44 	uid_t old_uid;
     45 	gid_t old_gid;
     46 
     47 	umask(0);
     48 	fd = shm_open(SHM_NAME, O_RDWR | O_CREAT,
     49 		      S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH |
     50 		      S_IWOTH);
     51 
     52 	if (fd == -1) {
     53 		perror("An error occurs when calling shm_open()");
     54 		return PTS_UNRESOLVED;
     55 	}
     56 
     57 	if (ftruncate(fd, BUF_SIZE) != 0) {
     58 		perror("An error occurs when calling ftruncate()");
     59 		shm_unlink(SHM_NAME);
     60 		return PTS_UNRESOLVED;
     61 	}
     62 
     63 	if (fstat(fd, &stat_buf) != 0) {
     64 		perror("An error occurs when calling fstat()");
     65 		shm_unlink(SHM_NAME);
     66 		return PTS_UNRESOLVED;
     67 	}
     68 	old_uid = stat_buf.st_uid;
     69 	old_gid = stat_buf.st_gid;
     70 
     71 	/* search for the first user which is non root and which is not the
     72 	   current user */
     73 	while ((pw = getpwent()) != NULL)
     74 		if (strcmp(pw->pw_name, "root") && pw->pw_uid != getuid())
     75 			break;
     76 
     77 	if (pw == NULL) {
     78 		printf("There is no other user than current and root.\n");
     79 		shm_unlink(SHM_NAME);
     80 		return PTS_UNRESOLVED;
     81 	}
     82 
     83 	if (seteuid(pw->pw_uid) != 0) {
     84 		if (errno == EPERM) {
     85 			printf
     86 			    ("You don't have permission to change your UID.\nTry to rerun this test as root.\n");
     87 		} else {
     88 			perror("An error occurs when calling seteuid()");
     89 		}
     90 		shm_unlink(SHM_NAME);
     91 		return PTS_UNRESOLVED;
     92 	}
     93 
     94 	printf("Testing with user '%s' (uid: %i)\n", pw->pw_name, pw->pw_uid);
     95 
     96 	fd = shm_open(SHM_NAME, O_RDWR | O_TRUNC, 0);
     97 	if (fd == -1) {
     98 		perror("An error occurs when calling shm_open()");
     99 		seteuid(getuid());
    100 		shm_unlink(SHM_NAME);
    101 		return PTS_UNRESOLVED;
    102 	}
    103 
    104 	if (fstat(fd, &stat_buf) != 0) {
    105 		perror("An error occurs when calling fstat()");
    106 		seteuid(getuid());
    107 		shm_unlink(SHM_NAME);
    108 		return PTS_UNRESOLVED;
    109 	}
    110 
    111 	seteuid(getuid());
    112 	shm_unlink(SHM_NAME);
    113 
    114 	if (stat_buf.st_uid == old_uid && stat_buf.st_gid == old_gid) {
    115 		printf("Test PASSED\n");
    116 		return PTS_PASS;
    117 	}
    118 
    119 	if (stat_buf.st_uid != old_uid)
    120 		printf("The user ID has changed.\n");
    121 	if (stat_buf.st_gid != old_gid)
    122 		printf("The group ID has changed.\n");
    123 	return PTS_FAIL;
    124 }
    125