Git init
[external/insserv.git] / debian / patches / 50_symlink_in_initddir.patch
1 Purpose: Defend against symlinks in init.d/ to other scripts in init.d/
2 Fixes:   #485045
3 Status:  Work in progress.
4 ---
5 Index: insserv/insserv.c
6 ===================================================================
7 --- insserv.orig/insserv.c      2009-09-26 22:35:39.000000000 +0200
8 +++ insserv/insserv.c   2009-09-26 22:35:44.000000000 +0200
9 @@ -2542,11 +2542,12 @@
10         errno = 0;
11  
12         /* d_type seems not to work, therefore use (l)stat(2) */
13 -       if (xstat(dfd, d->d_name, &st_script) < 0) {
14 +       if (xlstat(dfd, d->d_name, &st_script) < 0) {
15             warn("can not stat(%s)\n", d->d_name);
16             continue;
17         }
18 -       if (!S_ISREG(st_script.st_mode) || !(S_IXUSR & st_script.st_mode))
19 +       if ((!S_ISLNK(st_script.st_mode) && !S_ISREG(st_script.st_mode)) ||
20 +           !(S_IXUSR & st_script.st_mode))
21         {
22             if (S_ISDIR(st_script.st_mode))
23                 continue;
24 @@ -2555,6 +2556,43 @@
25             continue;
26         }
27  
28 +       /*
29 +        * Do extra sanity checking of symlinks in init.d/ dir, except if it
30 +        * is named reboot, as that is a special case on SUSE
31 +        */
32 +       if (S_ISLNK(st_script.st_mode) && ((strcmp(d->d_name, "reboot") != 0)))
33 +       {
34 +           char * base;
35 +           char linkbuf[PATH_MAX+1];
36 +           int  linklen;
37 +
38 +           linklen = xreadlink(dfd, d->d_name, linkbuf, sizeof(linkbuf)-1);
39 +           if (linklen < 0)
40 +               continue;
41 +           linkbuf[linklen] = '\0';
42 +
43 +           /* skip symbolic links to other scripts in this relative path */
44 +           if (!(base = strrchr(linkbuf, '/'))) {
45 +               if (isarg)
46 +                   warn("script %s is a symlink to another script, skipped!\n",
47 +                        d->d_name);
48 +               continue;
49 +           }
50 +
51 +           /* stat the symlink target and make sure it is a valid script */
52 +           if (xstat(dfd, d->d_name, &st_script) < 0)
53 +               continue;
54 +
55 +           if (!S_ISREG(st_script.st_mode) || !(S_IXUSR & st_script.st_mode)) {
56 +               if (S_ISDIR(st_script.st_mode))
57 +                   continue;
58 +               if (isarg)
59 +                   warn("script %s is not an executable regular file, skipped!\n",
60 +                        d->d_name);
61 +               continue;
62 +           }
63 +       }
64 +
65         if (!strncmp(d->d_name, "README", strlen("README"))) {
66             if (isarg)
67                 warn("script name %s is not valid, skipped!\n", d->d_name);