From: Rainer Weikusat on
gordonb.zz80w(a)burditt.org (Gordon Burditt) writes:
>>> I add some code in vfs. For example, it allows apache to access /var/
>>> www but prevents root user from accessing /var/www/index.html by vi.
>
> So what prevents root from using su to apache?

You are overestmating the techical sophistication of this change:

current->comm is a member of the struct task_struct defined in
current->include/linux/sched.h and documented as quoted below:

char comm[TASK_COMM_LEN]; /* executable name excluding path
From: Wanna-Be Sys Admin on
lovecreatesbeauty(a)gmai1.c0m wrote:

> On Nov 11, 9:44 am, "lovecreatesbea...(a)gmai1.c0m"
> <lovecreatesbea...(a)gmail.com> wrote:
>> On Nov 10, 6:26 pm, Edwin van den Oetelaar <newsgro...(a)oetelaar.com>
>> wrote:
>>
>> > lovecreatesbea...(a)gmai1.c0m wrote:
>> > > I encountered such an requirement of implementing a system that:
>>
>> > > 1. system accounts including root can't directly access file or
>> > > data on this system;
>>
>> > That would be strange.
>> > You could use a userspace application that does
>> > encrypting/decrypting of files on disk. This way, the root user can
>> > read the *file* but not decrypt its *contents* (data). Deleting the
>> > file is still possible.
>>
>> Thank you.
>>
>> I proposed ccrypt for it but it was not adopted.
>>
>> > > 2. only specific application, ie. http server (apache) can access
>> > > file on this system; (so apache linux user ie. www-data should be
>> > > allowed on it)
>>
>> > If you do your encryption/decryption/authentication inside the
>> > application that would work.
>>
>> > > 3. apache passes web user accounts (not linux system account ie.
>> > > root) to this system; and this system will present the apache
>> > > application with the files (in format of linux file system
>> > > hierarchy) related to the specified web users;
>>
>> > Does not compute, but take a look at FUSE, maybe filesystems in
>> > UserSpace help you.
>>
>> Fuse faq 1.5[1] states a situation that users including root can't
>> access filesystems mounted by other users. I tried fuse example
>> hello.c. Other problem is that I don't figure out
>>
>> how to make files in fuse persistent to physical media? or
>> how to map (mount?) fuse with a existing file system? or
>> how to format a fuse file system to physical media (we can format
>> ext3 but not fuse)?
>>
>> > > And I have some queries about it:
>>
>> > > Is there conceptual wrong in this requirement?
>>
>> > I think so. Instead of making the whole system more secure it
>> > introduces a lot of complexity that can break in unexpected ways.
>> > If you use normal setup with *sane* security setup it would be
>> > easier to setup and maintain.
>>
>> > > Can it be done in way of linux kernel file system, ie. ext2,
>> > > ext3? How to program this kind of customized file system?
>>
>> > Where / Why is this strange setup required? Is the rest of the
>> > system as secure? SSH/Certificates etc?
>>
>> I am supervised by an amateurish supervisor and I myself am not
>> professional enough to convey all the plans and ideas to correct
>> solutions on linux with C quickly enough. It seems that I / We are
>> doing some fake projects.
>>
>>
[1]http://sourceforge.net/apps/mediawiki/fuse/index.php?title=FAQ#Why_do...
>
>
> I add some code in vfs. For example, it allows apache to access /var/
> www but prevents root user from accessing /var/www/index.html by vi.
> My supervisor prefers this kind of solution. But I am a little upset
> on rough change like this.
>
>
> --- a\linux-2.6.30.4\fs\open.c 2009-07-31 06:34:48.000000000 +-0800
> +++ b\linux-2.6.30.4\fs\open.c 2009-11-13 14:34:45.000000000 +-0800
> @@ -1026,12 +1026,20 @@
> EXPORT_SYMBOL(fd_install);
>
> long do_sys_open(int dfd, const char __user *filename, int flags, int
> mode)
> {
> char *tmp = getname(filename);
> int fd = PTR_ERR(tmp);
> + char *s1 = "/var/www";
> + char *s2 = "apache2";
> +
> + if (strstr(filename, s1) && strcmp(s2, current->comm)){
> + printk("%s:%d, %s, %s\n", __FILE__, __LINE__,
> + current->comm, filename);
> + return fd;
> + }
>
> if (!IS_ERR(tmp)) {
> fd = get_unused_fd_flags(flags);
> if (fd >= 0) {
> struct file *f = do_filp_open(dfd, tmp, flags, mode, 0);
> if (IS_ERR(f)) {

What good does that do? The root user can use any alternative binary or
command to do whatever they want anyway, not to mention to install or
download the binary and replace the one you've modified. Sure, a root
owned process might not be able to access, read or modify a file using
a binary that says "if you're uid 0, then end the process", but that
doesn't mean a thing. That is not a solution by any stretch.
--
Not really a wanna-be, but I don't know everything.
From: David Schwartz on
On Nov 13, 2:49 am, Rainer Weikusat <rweiku...(a)mssgmbh.com> wrote:

> >  long do_sys_open(int dfd, const char __user *filename, int flags, int
> > mode)
> >  {
> >    char *tmp = getname(filename);
> >    int fd = PTR_ERR(tmp);
> > +  char *s1 = "/var/www";
> > +  char *s2 = "apache2";
> > +
> > +  if (strstr(filename, s1) && strcmp(s2, current->comm)){
> > +          printk("%s:%d, %s, %s\n", __FILE__, __LINE__,
> > +                                          current->comm, filename);
> > +          return fd;
> > +  }

> The most glaring problem with this is that this will (probably, I
> haven't tested it) allow access to any process whose corresponding
> binary is named apache2. Try
>
> cd /bin
> ln ed apache2
> ./apache2 /var/www/index.html
>
> as root for a demonstration (assuming /bin/ed exists, of course).

And, of course, 'root' can open the files indirectly by grabbing hooks
to them from the 'proc' filesystem when Apache opens them. The 'root'
user could even write a program to scan the 'proc' filesystem for
Apache open files and copy out each file as 'Apache' opens it using
its '/proc/<pid>/fd/<num>' name which won't match your 'strstr' test.

That code is, frankly, sheer idiocy.

That's not even a sensible way if the intent is to prevent 'root' from
accessing it by accident and is sure as heck isn't sensible if the
intent is to prevent 'root' from doing so maliciously.

DS
From: Wanna-Be Sys Admin on
David Schwartz wrote:

> On Nov 13, 2:49 am, Rainer Weikusat <rweiku...(a)mssgmbh.com> wrote:
>
>> > long do_sys_open(int dfd, const char __user *filename, int flags,
>> > int mode)
>> > {
>> > char *tmp = getname(filename);
>> > int fd = PTR_ERR(tmp);
>> > +  char *s1 = "/var/www";
>> > +  char *s2 = "apache2";
>> > +
>> > +  if (strstr(filename, s1) && strcmp(s2, current->comm)){
>> > +          printk("%s:%d, %s, %s\n", __FILE__, __LINE__,
>> > +                                          current->comm,
>> > filename); +          return fd;
>> > +  }
>
>> The most glaring problem with this is that this will (probably, I
>> haven't tested it) allow access to any process whose corresponding
>> binary is named apache2. Try
>>
>> cd /bin
>> ln ed apache2
>> ./apache2 /var/www/index.html
>>
>> as root for a demonstration (assuming /bin/ed exists, of course).
>
> And, of course, 'root' can open the files indirectly by grabbing hooks
> to them from the 'proc' filesystem when Apache opens them. The 'root'
> user could even write a program to scan the 'proc' filesystem for
> Apache open files and copy out each file as 'Apache' opens it using
> its '/proc/<pid>/fd/<num>' name which won't match your 'strstr' test.
>
> That code is, frankly, sheer idiocy.
>
> That's not even a sensible way if the intent is to prevent 'root' from
> accessing it by accident and is sure as heck isn't sensible if the
> intent is to prevent 'root' from doing so maliciously.
>
> DS

Agreed, I just don't understand the point of any of this goal. Why not
just host on your own system, where only you are root and add all of
the appropriate hoops to jump through if you want to make it more
difficult to get root, if you're concerned someone else might get root.
Why have root not have read/write normally, if you can trust it can be
fine to sit there on its own, unused (for all intents and purposes).
Then, who cares? If you can't trust root, you shouldn't use the
system. If you can, what's the issue? You'll need super user access
on a system to try and get around all of these things anyway, to try
and make it work how you want, and for what? I just don't understand?
Are you just trying to prevent root user from making a mistake?
--
Not really a wanna-be, but I don't know everything.
From: lovecreatesbeauty on
On Nov 13, 6:49 pm, Rainer Weikusat <rweiku...(a)mssgmbh.com> wrote:
>
> The most glaring problem with this is that this will (probably, I
> haven't tested it) allow access to any process whose corresponding
> binary is named apache2. Try
>
> cd /bin
> ln ed apache2
> ./apache2 /var/www/index.html
>
> as root for a demonstration (assuming /bin/ed exists, of course).
>
> You really should be using the existing facilities for extended access
> control, such as capabilities or one of the MAC-frameworks instead of
> trying to 'roll your own' in a that crude fashion.- Hide quoted text -
>

Thank you.

I didn't get the full pathname of filename in the previous code. It
doesn't handle this situation:

# cd /var
# vi www/index.html

Did you also mean this point? My new code:

(I rebuilt the source and reinstalled the kernel successfully on
debian hosted on VMWare. After I increased memory from 1536M to 2048M
in VMWare and reboot, I got: Kernel panic: no init found. Try passing
init= option to kernel. Dunno why.)


--- a\linux-2.6.26\fs\open.c 2008-07-14 05:51:30.000000000 +-0800
+++ b\linux-2.6.26\fs\open.c 2009-11-25 15:59:25.000000000 +-0800
@@ -1078,16 +1078,74 @@
rcu_assign_pointer(fdt->fd[fd], file);
spin_unlock(&files->file_lock);
}

EXPORT_SYMBOL(fd_install);

+/* strrvs is by jian hua li, http://www.grex.org/~jhl/miscc.txt */
+static unsigned char *strrvs(unsigned char *p)
+{
+ unsigned char *p1, *p2, ch;
+
+ for (p1 = p; *(p1 + 1); p1++) ;
+ for (p2 = p; p2 < p1; p2++, p1--)
+ ch = *p2, *p2 = *p1, *p1 = ch;
+ return p;
+}
+
long do_sys_open(int dfd, const char __user *filename, int flags, int
mode)
{
char *tmp = getname(filename);
int fd = PTR_ERR(tmp);
+ char *s1 = "/var/www";
+ char *s2 = "apache2";
+ unsigned char fullname[2048] = {'\0'}; /* temporary length */
+ struct dentry *dentry = current->fs->pwd.dentry;
+
+ if (filename[0] != '/'){
+ strncat(fullname, strrvs(filename), sizeof fullname - 1);
+ if (filename[0] == '.' && filename[1] == '.'){
+ /* ../a.c: drop ../ */
+ fullname[strlen(fullname) - 1] = '\0';
+ fullname[strlen(fullname) - 1] = '\0';
+ } else {
+ /* a.c, ./a.c: plus dentry->d_name.name */
+ strncat(fullname, "/", sizeof fullname - 1);
+ strncat(fullname, strrvs(dentry->d_name.name), sizeof fullname -
1);
+ strrvs(dentry->d_name.name);
+ }
+ while (dentry->d_parent->d_name.name[0] != '/'){
+ strncat(fullname, "/", sizeof fullname - 1);
+ strncat(fullname, strrvs(dentry->d_parent->d_name.name), sizeof
fullname - 1);
+ strrvs(dentry->d_parent->d_name.name);
+ dentry = dentry->d_parent;
+ }
+ strncat(fullname, strrvs(dentry->d_parent->d_name.name), sizeof
fullname - 1);
+ strrvs(dentry->d_parent->d_name.name);
+ }
+
+ if (strstr(fullname, s1) && strcmp(current->comm, s2)){
+ printk("%s:%d, %s, %s, %s\n", __FILE__, __LINE__, current->comm,
filename,
+ current->fs->pwd.dentry->d_parent->d_iname);
+ return -EPERM;
+ }

if (!IS_ERR(tmp)) {
fd = get_unused_fd_flags(flags);
if (fd >= 0) {
struct file *f = do_filp_open(dfd, tmp, flags, mode);
if (IS_ERR(f)) {