In modern Unix system, one user can belong to more than one group besides the primary group.
In Current Implementation(UBUNTU):
ubuntu@ip-172-31-23-227:~$ grep ubuntu /etc/passwd
ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash
ubuntu@ip-172-31-23-227:~$ grep ubuntu /etc/group
adm:x:4:syslog,ubuntu
dialout:x:20:ubuntu
cdrom:x:24:ubuntu
floppy:x:25:ubuntu
sudo:x:27:ubuntu
audio:x:29:ubuntu
dip:x:30:ubuntu
video:x:44:ubuntu
plugdev:x:46:ubuntu
netdev:x:102:ubuntu
ubuntu:x:1000:
Above code means, at /etc/passwd, current user: "ubuntu" has user id(3rd field): 1000, group id(4th field): 1000, which is also its primary group.At /etc/group, it lists all groups information at this system, for one group record, it is "group name, group password, group id, and then lastly a list of users". In this case, user "ubuntu" belongs to many groups listed here.
2. System Calls:
getgroups is used to return all groups current process belong to.
setgroups is used to set up related groups for the current user
initgroups is used to initialize current user's groups.
ubuntu@ip-172-31-23-227:~$ less /usr/include/unistd.h
......
/* If SIZE is zero, return the number of supplementary groups
the calling process is in. Otherwise, fill in the group IDs
of its supplementary groups in LIST and return the number written. */
extern int getgroups (int __size, __gid_t __list[]) __THROW __wur;
......
ubuntu@ip-172-31-23-227:~$ less /usr/include/grp.h
......
/* Set the group set for the current user to GROUPS (N of them). */
extern int setgroups (size_t __n, const __gid_t *__groups) __THROW;
......
/* Initialize the group set for the current user
by reading the group database and using all groups
of which USER is a member. Also include GROUP.
This function is not part of POSIX and therefore no official
cancellation point. But due to similarity with an POSIX interface
or due to the implementation it is a cancellation point and
therefore not marked with __THROW. */
extern int initgroups (const char *__user, __gid_t __group);
......
fileio.c:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<grp.h>
int getCurrentGroups(int* gids)
{
// Get group list cuurent user belongs to
int num_group;
if((num_group = getgroups(100, gids)) < 0) {
printf("getgroups error!\n");
exit(1);
}
int i;
printf("number of groups: %d\n", num_group);
for (i = 0; i < num_group; i++) {
printf("%d ", gids[i]);
}
printf("\n");
return num_group;
}
int main(int argc, char* argv[])
{
int gids[100];
int num_group;
num_group = getCurrentGroups(gids);
// Setup group list, note, we need to have super
// user permission to call following system calls
gids[num_group] = 3;
if(setgroups(num_group+1, gids) < 0) {
printf("setgroups error!\n");
exit(2);
}
num_group = getCurrentGroups(gids);
// Init groups
if(initgroups("root", 0) < 0) {
printf("initgroups error!\n");
exit(3);
}
num_group = getCurrentGroups(gids);
exit(0);
}
shell:
1) Run the program will current user, failed on setgroups, since it needs super user permission
2) Run the program with the super user permission, good for this time. It firstly get all user groups of super user "root", it only belongs to one group with id 0, then we use "setgroups" to add another groupid 3 to super user, then we call getgroups to output groups again, we have a new group! Lastly we call initgroups with user name "root", and basegid: 0 per password file, it just scan the password file and group file and load up every thing.
This example indicate that: all these system calls never touch the password file and group file, even if we call "setgroups" to change the supplementary group information we only change it temporarily for current process, it won't be change permanently on disk.
ubuntu@ip-172-31-23-227:~$ ./io.out
number of groups: 11
4 20 24 25 27 29 30 44 46 102 1000
setgroups error!
ubuntu@ip-172-31-23-227:~$ sudo ./io.out
number of groups: 1
0
number of groups: 2
0 3
number of groups: 1
0
No comments:
Post a Comment