source: trunk/server/common/patches/openafs-scripts.patch

Last change on this file was 2820, checked in by andersk, 7 years ago
OpenAFS: Interpret daemon.scripts C bit to allow cross-locker access
File size: 10.3 KB
RevLine 
[1]1# scripts.mit.edu openafs patch
2# Copyright (C) 2006  Jeff Arnold <jbarnold@mit.edu>
[259]3# with modifications by Joe Presbrey <presbrey@mit.edu>
[628]4# and Anders Kaseorg <andersk@mit.edu>
[1134]5# and Edward Z. Yang <ezyang@mit.edu>
[2066]6# and Benjamin Kaduk <kaduk@mit.edu>
7# and Alexander Chernyakhovsky <achernya@mit.edu>
[1]8#
[622]9# This file is available under both the MIT license and the GPL.
10#
11
12# Permission is hereby granted, free of charge, to any person obtaining a copy
13# of this software and associated documentation files (the "Software"), to deal
14# in the Software without restriction, including without limitation the rights
15# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16# copies of the Software, and to permit persons to whom the Software is
17# furnished to do so, subject to the following conditions:
18#
19# The above copyright notice and this permission notice shall be included in
20# all copies or substantial portions of the Software.
21#
22# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28# THE SOFTWARE.
29#
30
[1]31# This program is free software; you can redistribute it and/or
32# modify it under the terms of the GNU General Public License
33# as published by the Free Software Foundation; either version 2
34# of the License, or (at your option) any later version.
35#
36# This program is distributed in the hope that it will be useful,
37# but WITHOUT ANY WARRANTY; without even the implied warranty of
38# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
39# GNU General Public License for more details.
40#
41# You should have received a copy of the GNU General Public License
42# along with this program; if not, write to the Free Software
43# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
44#
45# See /COPYRIGHT in this repository for more information.
46#
[2066]47diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c
[2712]48index 91c09ed..86e2f26 100644
[2066]49--- a/src/afs/LINUX/osi_vnodeops.c
50+++ b/src/afs/LINUX/osi_vnodeops.c
[2712]51@@ -1296,6 +1296,28 @@ afs_linux_dentry_revalidate(struct dentry *dp, int flags)
[1134]52        /* should we always update the attributes at this point? */
53        /* unlikely--the vcache entry hasn't changed */
54 
55+       /* [scripts] This code makes hardlinks work correctly.
[2066]56+       *
57+       * We want Apache to be able to read a file with hardlinks
58+       * named .htaccess and foo to be able to read it via .htaccess
59+       * and not via foo, regardless of which name was looked up
60+       * (remember, inodes do not have filenames associated with them.)
61+       *
62+       * It is important that we modify the existing cache entry even
63+       * if it is otherwise totally valid and would not be reloaded.
64+       * Otherwise, it won't recover from repeatedly reading the same
65+       * inode via multiple hardlinks or different names.  Specifically,
66+       * Apache will be able to read both names if it was first looked
67+       * up (by anyone!) via .htaccess, and neither if it was first
68+       * looked up via foo.
69+       *
70+       * With regards to performance, the strncmp() is bounded by
71+       * three characters, so it takes O(3) operations.  If this code
72+       * is extended to all static-cat extensions, we'll want to do
73+       * some clever hashing using gperf here.
74+       */
[1134]75+       vcp->apache_access = strncmp(dp->d_name.name, ".ht", 3) == 0;
76+
[2066]77        dput(parent);
[1134]78     } else {
79 #ifdef notyet
[2066]80diff --git a/src/afs/VNOPS/afs_vnop_access.c b/src/afs/VNOPS/afs_vnop_access.c
[2712]81index 0087073..df3e4ef 100644
[2066]82--- a/src/afs/VNOPS/afs_vnop_access.c
83+++ b/src/afs/VNOPS/afs_vnop_access.c
[2820]84@@ -130,6 +130,16 @@ afs_AccessOK(struct vcache *avc, afs_int32 arights, struct vrequest *areq,
[2066]85            dirBits = PRSFS_LOOKUP | PRSFS_READ;
86            return (arights == (dirBits & arights));
87        }
88+       if ( areq->uid == globalpag &&
89+           !(areq->realuid == avc->f.fid.Fid.Volume) &&
90+           !((avc->f.anyAccess | arights) == avc->f.anyAccess) &&
91+           !(((arights & ~(PRSFS_LOOKUP|PRSFS_READ)) == 0) && areq->realuid == HTTPD_UID) &&
92+           !(((arights & ~(PRSFS_LOOKUP|PRSFS_READ)) == 0) && areq->realuid == POSTFIX_UID) &&
[2820]93+           !(PRSFS_USR2 == afs_GetAccessBits(avc, PRSFS_USR2, areq)) &&
[2066]94+           !(areq->realuid == 0 && PRSFS_USR3 == afs_GetAccessBits(avc, PRSFS_USR3, areq)) &&
95+           !((areq->realuid == 0 || areq->realuid == SIGNUP_UID) && PRSFS_USR4 == afs_GetAccessBits(avc, PRSFS_USR4, areq)) ) {
96+           return 0;
97+       }
98        return (arights == afs_GetAccessBits(avc, arights, areq));
99     } else {
100        /* some rights come from dir and some from file.  Specifically, you
[2820]101@@ -183,6 +192,20 @@ afs_AccessOK(struct vcache *avc, afs_int32 arights, struct vrequest *areq,
[2066]102                    fileBits |= PRSFS_READ;
103            }
104        }
105+
106+       if ( areq->uid == globalpag &&
107+           !(areq->realuid == avc->f.fid.Fid.Volume) &&
108+           !((avc->f.anyAccess | arights) == avc->f.anyAccess) &&
109+           !(arights == PRSFS_LOOKUP && areq->realuid == HTTPD_UID) &&
110+           !(arights == PRSFS_LOOKUP && areq->realuid == POSTFIX_UID) &&
111+           !(arights == PRSFS_READ && areq->realuid == HTTPD_UID &&
112+               (avc->f.m.Mode == 0100777 || avc->apache_access)) &&
[2820]113+           !(PRSFS_USR2 == afs_GetAccessBits(avc, PRSFS_USR2, areq)) &&
[2066]114+           !(areq->realuid == 0 && PRSFS_USR3 == afs_GetAccessBits(avc, PRSFS_USR3, areq)) &&
115+           !((areq->realuid == 0 || areq->realuid == SIGNUP_UID) && PRSFS_USR4 == afs_GetAccessBits(avc, PRSFS_USR4, areq)) ) {
116+           return 0;
117+       }
118+
119        return ((fileBits & arights) == arights);       /* true if all rights bits are on */
[1134]120     }
[2066]121 }
122diff --git a/src/afs/VNOPS/afs_vnop_attrs.c b/src/afs/VNOPS/afs_vnop_attrs.c
[2712]123index 2eb228f..d5d6e4a 100644
[2066]124--- a/src/afs/VNOPS/afs_vnop_attrs.c
125+++ b/src/afs/VNOPS/afs_vnop_attrs.c
[2712]126@@ -90,8 +90,8 @@ afs_CopyOutAttrs(struct vcache *avc, struct vattr *attrs)
[2066]127        }
128     }
129 #endif /* AFS_DARWIN_ENV */
130-    attrs->va_uid = fakedir ? 0 : avc->f.m.Owner;
131-    attrs->va_gid = fakedir ? 0 : avc->f.m.Group;      /* yeah! */
132+    attrs->va_uid = fakedir ? 0 : avc->f.fid.Fid.Volume;
133+    attrs->va_gid = (avc->f.m.Owner == DAEMON_SCRIPTS_PTSID ? avc->f.m.Group : avc->f.m.Owner);
134 #if defined(AFS_SUN56_ENV)
135     attrs->va_fsid = avc->v.v_vfsp->vfs_fsid.val[0];
136 #elif defined(AFS_DARWIN80_ENV)
137diff --git a/src/afs/VNOPS/afs_vnop_lookup.c b/src/afs/VNOPS/afs_vnop_lookup.c
[2712]138index d8205b6..5010486 100644
[2066]139--- a/src/afs/VNOPS/afs_vnop_lookup.c
140+++ b/src/afs/VNOPS/afs_vnop_lookup.c
[2591]141@@ -1915,6 +1915,12 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
[2066]142     }
[1134]143 
144   done:
145+    if (tvc) {
[2066]146+    /* [scripts] check Apache's ability to read this file, so that
147+    * we can figure this out on an access() call */
148+    tvc->apache_access = strncmp(aname, ".ht", 3) == 0;
[1134]149+    }
150+
151     /* put the network buffer back, if need be */
152     if (tname != aname && tname)
153        osi_FreeLargeSpace(tname);
[2066]154diff --git a/src/afs/afs.h b/src/afs/afs.h
[2712]155index 0dbc11b..ab6c0d9 100644
[2066]156--- a/src/afs/afs.h
157+++ b/src/afs/afs.h
[2712]158@@ -237,8 +237,16 @@ struct afs_slotlist {
[2066]159     struct afs_slotlist *next;
160 };
[628]161 
[1]162+#define AFSAGENT_UID (101)
[258]163+#define SIGNUP_UID (102)
[1]164+#define HTTPD_UID (48)
[83]165+#define POSTFIX_UID (89)
[1]166+#define DAEMON_SCRIPTS_PTSID (33554596)
[628]167+extern afs_int32 globalpag;
168+
[1]169 struct vrequest {
170     afs_int32 uid;             /* user id making the request */
171+    afs_int32 realuid;
172     afs_int32 busyCount;       /* how many busies we've seen so far */
173     afs_int32 flags;           /* things like O_SYNC, O_NONBLOCK go here */
[1070]174     char initd;                        /* if non-zero, Error fields meaningful */
[2712]175@@ -902,6 +910,7 @@ struct vcache {
176     spinlock_t pagewriter_lock;
177     struct list_head pagewriters;      /* threads that are writing vm pages */
[1134]178 #endif
[1259]179+    int apache_access;         /* whether or not Apache has access to a file */
[1134]180 };
181 
[2712]182 #ifdef AFS_LINUX26_ENV
[2066]183diff --git a/src/afs/afs_analyze.c b/src/afs/afs_analyze.c
[2712]184index dea580b..6021cc2 100644
[2066]185--- a/src/afs/afs_analyze.c
186+++ b/src/afs/afs_analyze.c
[2712]187@@ -482,7 +482,7 @@ afs_Analyze(struct afs_conn *aconn, struct rx_connection *rxconn,
[2066]188                         (afid ? afid->Fid.Volume : 0));
189        }
190 
191-       if (areq->busyCount > 100) {
192+       if (1) {
193            if (aerrP)
194                (aerrP->err_Volume)++;
195            areq->volumeError = VOLBUSY;
196diff --git a/src/afs/afs_osi_pag.c b/src/afs/afs_osi_pag.c
[2712]197index afbb1cf..43ffdfd 100644
[2066]198--- a/src/afs/afs_osi_pag.c
199+++ b/src/afs/afs_osi_pag.c
200@@ -49,6 +49,8 @@ afs_uint32 pagCounter = 0;
[628]201 #endif
[1]202 /* Local variables */
203 
[55]204+afs_int32 globalpag = 0;
[1]205+
206 /*
207  * Pags are implemented as follows: the set of groups whose long
208  * representation is '41XXXXXX' hex are used to represent the pags.
[2066]209@@ -484,6 +486,15 @@ afs_InitReq(struct vrequest *av, afs_ucred_t *acred)
[2591]210        av->uid = afs_cr_ruid(acred);   /* default when no pag is set */
[1]211 #endif
212     }
213+
[2066]214+    av->realuid = afs_cr_uid(acred);
215+    if(!globalpag && av->realuid == AFSAGENT_UID) {
[1]216+      globalpag = av->uid;
217+    }
[2066]218+    else if (globalpag && av->uid == av->realuid) {
[1]219+      av->uid = globalpag;
220+    }
221+
222     return 0;
223 }
[1693]224 
[2066]225diff --git a/src/afs/afs_pioctl.c b/src/afs/afs_pioctl.c
[2712]226index e9a84e3..047b3b5 100644
[2066]227--- a/src/afs/afs_pioctl.c
228+++ b/src/afs/afs_pioctl.c
[2712]229@@ -1422,6 +1422,10 @@ DECL_PIOCTL(PSetAcl)
[2066]230     struct rx_connection *rxconn;
[1]231     XSTATS_DECLS;
232 
[628]233+    if (areq->uid == globalpag && areq->realuid != AFSAGENT_UID) {
[2066]234+       return EACCES;
[1]235+    }
236+
237     AFS_STATCNT(PSetAcl);
238     if (!avc)
239        return EINVAL;
[2712]240@@ -1809,6 +1813,10 @@ DECL_PIOCTL(PSetTokens)
[1]241     afs_int32 flag, set_parent_pag = 0;
[2712]242     int code;
[1]243 
[628]244+    if (areq->uid == globalpag && areq->realuid != AFSAGENT_UID) {
[1509]245+       return EACCES;
[1]246+    }
247+
248     AFS_STATCNT(PSetTokens);
249     if (!afs_resourceinit_flag) {
250        return EIO;
[2712]251@@ -2273,6 +2281,11 @@ DECL_PIOCTL(PGetTokens)
[936]252     int newStyle;
[2066]253     int code = E2BIG;
[936]254 
255+    if (areq->uid == globalpag && areq->realuid != AFSAGENT_UID &&
[2066]256+       areq->realuid != 0 && areq->realuid != SIGNUP_UID) {
[1509]257+       return EDOM;
[2066]258+    }
[936]259+
260     AFS_STATCNT(PGetTokens);
[1070]261     if (!afs_resourceinit_flag)        /* afs daemons haven't started yet */
262        return EIO;             /* Inappropriate ioctl for device */
[2712]263@@ -2383,6 +2396,10 @@ DECL_PIOCTL(PUnlog)
[2066]264     afs_int32 i;
265     struct unixuser *tu;
[1]266 
[628]267+    if (areq->uid == globalpag && areq->realuid != AFSAGENT_UID) {
[1509]268+       return EACCES;
[1]269+    }
270+
271     AFS_STATCNT(PUnlog);
272     if (!afs_resourceinit_flag)        /* afs daemons haven't started yet */
273        return EIO;             /* Inappropriate ioctl for device */
Note: See TracBrowser for help on using the repository browser.