aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/groups.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/groups.c')
-rw-r--r--kernel/groups.c35
1 files changed, 11 insertions, 24 deletions
diff --git a/kernel/groups.c b/kernel/groups.c
index d09727692a2a..434f6665f187 100644
--- a/kernel/groups.c
+++ b/kernel/groups.c
@@ -5,6 +5,7 @@
5#include <linux/export.h> 5#include <linux/export.h>
6#include <linux/slab.h> 6#include <linux/slab.h>
7#include <linux/security.h> 7#include <linux/security.h>
8#include <linux/sort.h>
8#include <linux/syscalls.h> 9#include <linux/syscalls.h>
9#include <linux/user_namespace.h> 10#include <linux/user_namespace.h>
10#include <linux/vmalloc.h> 11#include <linux/vmalloc.h>
@@ -76,32 +77,18 @@ static int groups_from_user(struct group_info *group_info,
76 return 0; 77 return 0;
77} 78}
78 79
79/* a simple Shell sort */ 80static int gid_cmp(const void *_a, const void *_b)
81{
82 kgid_t a = *(kgid_t *)_a;
83 kgid_t b = *(kgid_t *)_b;
84
85 return gid_gt(a, b) - gid_lt(a, b);
86}
87
80static void groups_sort(struct group_info *group_info) 88static void groups_sort(struct group_info *group_info)
81{ 89{
82 int base, max, stride; 90 sort(group_info->gid, group_info->ngroups, sizeof(*group_info->gid),
83 int gidsetsize = group_info->ngroups; 91 gid_cmp, NULL);
84
85 for (stride = 1; stride < gidsetsize; stride = 3 * stride + 1)
86 ; /* nothing */
87 stride /= 3;
88
89 while (stride) {
90 max = gidsetsize - stride;
91 for (base = 0; base < max; base++) {
92 int left = base;
93 int right = left + stride;
94 kgid_t tmp = group_info->gid[right];
95
96 while (left >= 0 && gid_gt(group_info->gid[left], tmp)) {
97 group_info->gid[right] = group_info->gid[left];
98 right = left;
99 left -= stride;
100 }
101 group_info->gid[right] = tmp;
102 }
103 stride /= 3;
104 }
105} 92}
106 93
107/* a simple bsearch */ 94/* a simple bsearch */