1. system accounts including root can't directly access file or data
on this system;
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)
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;
And I have some queries about it:
Is there conceptual wrong in this requirement?
Can it be done in way of linux kernel file system, ie. ext2, ext3?
How to program this kind of customized file system?
Thank you for your time.
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.
> 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.
>
> 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?
>
> Thank you for your time.
Where / Why is this strange setup required? Is the rest of the system as secure? SSH/Certificates etc?
Regards,
Edwin
Edwin van den Oetelaar <newsg...@oetelaar.com> wrote:
>That would be strange.
Agreed. Securing against root is somewhere between very difficult and
impossible, depending on exact OS you're using. Even with hardware encryption
support, a clever root user can find ways to get the keys.
Move such sensitive data to a system you can secure for real by not making
root available to people with lower priveleges.
>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.
Root can still get the keys or data out of memory, and/or patch the
application to alter the data at runtime. Among other things.
>> 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.
Nope. Root has control over the application.
>> Is there conceptual wrong in this requirement?
>I think so.
>Where / Why is this strange setup required? Is the rest of the system as
>secure? SSH/Certificates etc?
Agreed. This set of requirements is broken. Don't secure a system against
root, instead move the system to a secure one with different root access.
Having your webserver(s) be on different physical host(s) than your data
storage and security system(s) is fairly reasonable. Having them on the same
box and secure from root abuse is nigh impossible.
If you do what you're asking, you're guaranteed to get it wrong, and be no
more secure than if you just ignored the requirement to start with. Actually,
you'll be less secure because there's a class of threats you think you're
protected against when you're not.
--
Mark Rafn da...@dagon.net <http://www.dagon.net/>
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.
Easily enough done, except the one aspect where you want a non
privileged user access to things and to deny root. Why not just set it
up to work how you want and accept that root can still do what root
should be able to do? If you can't trust root user, host the
application on your own server and lock root down (you'll likely find
more issues with trying to keep the system secure and sane with
thinking the Apache user can be controlled, to not have to worry so
much about root).
--
Not really a wanna-be, but I don't know everything.
> 1. system accounts including root can't directly access file or data
> on this system;
[snip]
> Is there conceptual wrong in this requirement?
> Can it be done in way of linux kernel file system, ie. ext2, ext3?
> How to program this kind of customized file system?
Linux is not the right operating system for meeting requirements like
these. Linux is fundamentally built around a "root can do anything"
model.
However, I think this sounds like a nonsensical set of requirements.
What would the rationale for requirement 1 be? To prevent root from
deliberately causing problems? But he'll just do things indirectly, so
stopping him from doing things directly makes little sense. To prevent
him from accidentally accessing file or data? What does "directly"
even mean in this context?
DS
This is not correct. The traditional UNIX(*) security model includes
the notion of a superuser which has unrestricted access to
everything. Insofar particular privileged operations are supposed to
be made available to otherwise unprivileged users, this policy
descision is supposed to be implemented in application code. This is a
simple and unlimitedly flexible model which has been proven to be
sufficient for many real-world applications. It, howevers, suffers
from two important drawbacks:
- the TCB (trusted computing base) is extended to application
code, which is a very ill fit for 'the hack on it until it
works, although nobody knows how or why, and then move one
to the next problem' common development paradigm.
- it is simple. People who desire 'security' are likely to
have a bureaucratic mindset and 'simplictly' is inherently
un-bureaucratic.
Therefore, the 'Linux' security model is built around an ever growing
set of 'capabilites', ie particular tasks someone considers to be
'special' for some more-or-less random reason and which can be revoked
and granted to entities scheduled by the kernel ('threads' and
single-threaded processes) by using the corresponding system calls
according to a fairly elaborate model[*]. Details are documented in
capabilities(7), an online copy is available here:
http://www.kernel.org/doc/man-pages/online/pages/man7/capabilities.7.html
According to the documentation, it should be possible to meet the file
access requirement in this way. Another option would be to use
mandatory access control, ie SELinux (AppArmor loses another big set
of points because of people who try to play games with Wikipedia).
[*] So far, the most notable achievement of this 'new and
improved design' have been 'new and moderately interesting
ways to accomplish privilege escalation'.
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)) {
[...]
> 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;
> + }
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.
So what prevents root from using su to apache? What prevents root
from replacing apache with vi (while the real apache is still running)?
What prevents root from taking that code out of the kernel?
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
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.
> > 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?
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)) {
[..]
[ 1.541280] Kernel panic - not syncing: No init found. Try passing
init= option to kernel.
It seems caused by my code.
I add init=3 in menu.lst as:
kernel/boot/vmlinuz-2.6.26 root=/dev/sda1 ro quiet init=3
Still it has the problem.
The file /sbin/init is missing, or you have the wrong partition chosen
for root=. Try booting from a live CD of the same distro and copy that
file.
No. But this really doesn't matter since the approach you insist on
using cannot ever work.
[...]
> My new code:
[...]
> +/* 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);
Leaving the issue with the trashed dentries aside, I assume that a
file named tini/nibs/ simply doesn't exist on your system. But don't
worry to much about that --- since the system won't boot anymore,
files have successfully been secured against accesses of any user
without a screwdriver ...
This must be satire, right?
Stupid, there is never such usage of 'init', either "init 3",
or "init=/bin/what_ever_shell".
After checking some previous emails in this thread, I think you
should try SELinux or AppArmor, definitely you're going to a wrong
direction.
>
> (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.)
Obviously it's nothing to do with your physical memory size.
<snip stupid code>
You are definitely implementing a policy in kernel, and it's too stupid.
Stop.
thanks. I also saw that before myself. I thought I've fixed it.
if it can boot, how can you see that :)
I admit that it's a bit dangerous, but isn't the thing - custom kernel
done this way?
correction: (similar code applied to sys_unlink and sys_rename in
namei.c also)
--- 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-27 12:46:54.000000000 +-0800
@@ -1078,17 +1078,65 @@
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'};
+ unsigned char s[2048] = {'\0'};
+ struct dentry *dentry = current->fs->pwd.dentry;
+ if (filename[0] != '/'){
+ strncpy(s, filename, sizeof s - 1);
+ strncpy(fullname, strrvs(s), 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);
+ memset(s, '\0', sizeof s);
+ strncpy(s, dentry->d_name.name, sizeof s - 1);
+ strncat(fullname, strrvs(s), sizeof fullname - 1);
+ }
+ while (dentry->d_parent->d_name.name[0] != '/'){
+ strncat(fullname, "/", sizeof fullname - 1);
+ memset(s, '\0', sizeof s);
+ strncpy(s, dentry->d_parent->d_name.name, sizeof s - 1);
+ strncat(fullname, strrvs(s), sizeof fullname - 1);
+ dentry = dentry->d_parent;
+ }
+ memset(s, '\0', sizeof s);
+ strncpy(s, dentry->d_parent->d_name.name, sizeof s - 1);
+ strncat(fullname, strrvs(s), sizeof fullname - 1);
+ strrvs(fullname);
+ } else
+ strncpy(fullname, filename, sizeof fullname - 1);
+ 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)) {
put_unused_fd(fd);
> On Nov 25, 5:01 pm, "lovecreatesbea...@gmai1.c0m"
> <lovecreatesbea...@gmail.com> wrote:
> [..]
>
> correction: (similar code applied to sys_unlink and sys_rename in
> namei.c also)
>
...
Why are you still trying this solution? If you said so, I didn't see a
reply. Can you TRUST the root user? Are you just trying to make root
"think before doing"? You do realize root can do a ton of things to
circumvent this attempt at keeping root out of a directory/partition
that you only want Apache to have access to. This will never work.
You simply can not keep root from doing anything they want. Not in
this environment anyway. So, exactly what are you trying to keep root
out for? If it's just to make it so root run automated processes or
commands someone might run without thinking from doing things, then it
could work okay, but if you can't trust root, then you are screwed no
matter what you're trying. Anyway, it would be simple enough for root
to either unload a module, replacing it with another, upload their own
kernel, boot into a different one, or just run any of their processes
they want to read that directory as the Apache user anyway (which
instantly takes away all of your attempts to stop them from
read/access), and they needn't do anything special or complicated to do
that. So, what's the point of this?
update.
diff -uprN linux-2.6.18.orig/fs/namei.c linux-2.6.18/fs/namei.c
--- linux-2.6.18.orig/fs/namei.c 2009-12-01 16:20:12.000000000 +0800
+++ linux-2.6.18/fs/namei.c 2009-12-11 16:27:48.000000000 +0800
@@ -37,6 +37,9 @@
#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
+extern char fs_uit_wdsk_access_app[];
+extern char fs_uit_wdsk_access_pth[];
+
/* [Feb-1997 T. Schoebel-Theuer]
* Fundamental changes in the pathname lookup mechanisms (namei)
* were necessary because of omirr. The reason is that omirr needs
@@ -2075,6 +2078,17 @@ int vfs_unlink(struct inode *dir, struct
return error;
}
+/* 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;
+}
+
/*
* Make sure that the actual truncation of the file will occur
outside its
* directory's i_mutex. Truncate can take a long time if there is a
lot of
@@ -2088,6 +2102,64 @@ static long do_unlinkat(int dfd, const c
struct dentry *dentry;
struct nameidata nd;
struct inode *inode = NULL;
+ char *s1 = fs_uit_wdsk_access_pth; /*"/var/www;/root;/home/jhl"*/
+ char *s2 = fs_uit_wdsk_access_app; /*"apache2;tomcat;blahblah"*/
+ unsigned char fullname[512] = {'\0'};
+ unsigned char s[512] = {'\0'};
+ struct dentry *dent = current->fs->pwd /* .dentry */;
+ unsigned char *p;
+ unsigned int cnt = 0;
+
+ if (pathname[0] != '/'){
+ strncpy(s, pathname, sizeof s - 1);
+ strncpy(fullname, strrvs(s), sizeof fullname - 1);
+ if (pathname[0] == '.' && pathname[1] == '.'){
+ /* ../../a.c: drop all ../../ so drop three letters ../ then other
three, etc */
+ while (fullname[strlen(fullname) - 1] == '.' && fullname[strlen
(fullname) - 2] == '.'){
+ cnt++;
+ fullname[strlen(fullname) - 1] = '\0';
+ fullname[strlen(fullname) - 1] = '\0';
+ fullname[strlen(fullname) - 1] = '\0';
+ }
+ while (--cnt){
+ p = strrchr(fullname, '/');
+ *p = '\0';
+ }
+ } else if (pathname[0] == '.' && pathname[1] == '/'){
+ /* ./a.c: drop ./ and plus dentry->d_name.name */
+ fullname[strlen(fullname) - 1] = '\0';
+ fullname[strlen(fullname) - 1] = '\0';
+ strncat(fullname, "/", sizeof fullname - 1);
+ memset(s, '\0', sizeof s);
+ strncpy(s, dent->d_name.name, sizeof s - 1);
+ strncat(fullname, strrvs(s), sizeof fullname - 1);
+ } else {
+ /* a.c: plus dentry->d_name.name */
+ strncat(fullname, "/", sizeof fullname - 1);
+ memset(s, '\0', sizeof s);
+ strncpy(s, dent->d_name.name, sizeof s - 1);
+ strncat(fullname, strrvs(s), sizeof fullname - 1);
+ }
+ while (dent->d_parent->d_name.name[0] != '/'){
+ strncat(fullname, "/", sizeof fullname - 1);
+ memset(s, '\0', sizeof s);
+ strncpy(s, dent->d_parent->d_name.name, sizeof s - 1);
+ strncat(fullname, strrvs(s), sizeof fullname - 1);
+ dent = dent->d_parent;
+ }
+ memset(s, '\0', sizeof s);
+ strncpy(s, dent->d_parent->d_name.name, sizeof s - 1);
+ strncat(fullname, strrvs(s), sizeof fullname - 1);
+ strrvs(fullname);
+ } else
+ strncpy(fullname, pathname, sizeof fullname - 1);
+ p = strrchr(fullname, '/');
+ *p = '\0';
+ p = strstr(s1, fullname);
+ if (p && p[strlen(fullname)] == ';' && !strstr(s2, current->comm)){
+ printk("%s:%d, %s, %s, %s, %s\n", __FILE__, __LINE__, current-
>comm, fullname, s2, s1);
+ return -EPERM;
+ }
name = getname(pathname);
if(IS_ERR(name))
@@ -2529,6 +2601,64 @@ asmlinkage long sys_renameat(int olddfd,
int error;
char * from;
char * to;
+ char *s1 = fs_uit_wdsk_access_pth; /*"/var/www;/root;/home/jhl"*/
+ char *s2 = fs_uit_wdsk_access_app; /*"apache2;tomcat;blahblah"*/
+ unsigned char fullname[512] = {'\0'};
+ unsigned char s[512] = {'\0'};
+ struct dentry *dentry = current->fs->pwd /* .dentry */;
+ unsigned char *p;
+ unsigned int cnt = 0;
+
+ if (oldname[0] != '/'){
+ strncpy(s, oldname, sizeof s - 1);
+ strncpy(fullname, strrvs(s), sizeof fullname - 1);
+ if (oldname[0] == '.' && oldname[1] == '.'){
+ /* ../../a.c: drop all ../../ so drop three letters ../ then other
three, etc */
+ while (fullname[strlen(fullname) - 1] == '.' && fullname[strlen
(fullname) - 2] == '.'){
+ cnt++;
+ fullname[strlen(fullname) - 1] = '\0';
+ fullname[strlen(fullname) - 1] = '\0';
+ fullname[strlen(fullname) - 1] = '\0';
+ }
+ while (--cnt){
+ p = strrchr(fullname, '/');
+ *p = '\0';
+ }
+ } else if (oldname[0] == '.' && oldname[1] == '/'){
+ /* ./a.c: drop ./ and plus dentry->d_name.name */
+ fullname[strlen(fullname) - 1] = '\0';
+ fullname[strlen(fullname) - 1] = '\0';
+ strncat(fullname, "/", sizeof fullname - 1);
+ memset(s, '\0', sizeof s);
+ strncpy(s, dentry->d_name.name, sizeof s - 1);
+ strncat(fullname, strrvs(s), sizeof fullname - 1);
+ } else {
+ /* a.c: plus dentry->d_name.name */
+ strncat(fullname, "/", sizeof fullname - 1);
+ memset(s, '\0', sizeof s);
+ strncpy(s, dentry->d_name.name, sizeof s - 1);
+ strncat(fullname, strrvs(s), sizeof fullname - 1);
+ }
+ while (dentry->d_parent->d_name.name[0] != '/'){
+ strncat(fullname, "/", sizeof fullname - 1);
+ memset(s, '\0', sizeof s);
+ strncpy(s, dentry->d_parent->d_name.name, sizeof s - 1);
+ strncat(fullname, strrvs(s), sizeof fullname - 1);
+ dentry = dentry->d_parent;
+ }
+ memset(s, '\0', sizeof s);
+ strncpy(s, dentry->d_parent->d_name.name, sizeof s - 1);
+ strncat(fullname, strrvs(s), sizeof fullname - 1);
+ strrvs(fullname);
+ } else
+ strncpy(fullname, oldname, sizeof fullname - 1);
+ p = strrchr(fullname, '/');
+ *p = '\0';
+ p = strstr(s1, fullname);
+ if (p && p[strlen(fullname)] == ';' && !strstr(s2, current->comm)){
+ printk("%s:%d, %s, %s, %s, %s\n", __FILE__, __LINE__, current-
>comm, fullname, s2, s1);
+ return -EPERM;
+ }
from = getname(oldname);
if(IS_ERR(from))
diff -uprN linux-2.6.18.orig/fs/open.c linux-2.6.18/fs/open.c
--- linux-2.6.18.orig/fs/open.c 2009-12-01 16:20:12.000000000 +0800
+++ linux-2.6.18/fs/open.c 2009-12-11 16:28:12.000000000 +0800
@@ -31,6 +31,9 @@
#include <asm/unistd.h>
+char fs_uit_wdsk_access_app[1024] = {'\0'};
+char fs_uit_wdsk_access_pth[1024] = {'\0'};
+
int vfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{
int retval = -ENODEV;
@@ -1075,10 +1078,79 @@ void fastcall fd_install(unsigned int fd
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 = fs_uit_wdsk_access_pth; /*"/var/www;/root;/home/jhl"*/
+ char *s2 = fs_uit_wdsk_access_app; /*"apache2;tomcat;blahblah"*/
+ unsigned char fullname[512] = {'\0'};
+ unsigned char s[512] = {'\0'};
+ struct dentry *dentry = current->fs->pwd /* .dentry */;
+ unsigned char *p;
+ unsigned int cnt = 0;
+
+ if (filename[0] != '/'){
+ strncpy(s, filename, sizeof s - 1);
+ strncpy(fullname, strrvs(s), sizeof fullname - 1);
+ if (filename[0] == '.' && filename[1] == '.'){
+ /* ../../a.c: drop all ../../ so drop three letters ../ then other
three, etc */
+ while (fullname[strlen(fullname) - 1] == '.' && fullname[strlen
(fullname) - 2] == '.'){
+ cnt++;
+ fullname[strlen(fullname) - 1] = '\0';
+ fullname[strlen(fullname) - 1] = '\0';
+ fullname[strlen(fullname) - 1] = '\0';
+ }
+ while (--cnt){
+ p = strrchr(fullname, '/');
+ *p = '\0';
+ }
+ } else if (filename[0] == '.' && filename[1] == '/'){
+ /* ./a.c: drop ./ and plus dentry->d_name.name */
+ fullname[strlen(fullname) - 1] = '\0';
+ fullname[strlen(fullname) - 1] = '\0';
+ strncat(fullname, "/", sizeof fullname - 1);
+ memset(s, '\0', sizeof s);
+ strncpy(s, dentry->d_name.name, sizeof s - 1);
+ strncat(fullname, strrvs(s), sizeof fullname - 1);
+ } else {
+ /* a.c: plus dentry->d_name.name */
+ strncat(fullname, "/", sizeof fullname - 1);
+ memset(s, '\0', sizeof s);
+ strncpy(s, dentry->d_name.name, sizeof s - 1);
+ strncat(fullname, strrvs(s), sizeof fullname - 1);
+ }
+ while (dentry->d_parent->d_name.name[0] != '/'){
+ strncat(fullname, "/", sizeof fullname - 1);
+ memset(s, '\0', sizeof s);
+ strncpy(s, dentry->d_parent->d_name.name, sizeof s - 1);
+ strncat(fullname, strrvs(s), sizeof fullname - 1);
+ dentry = dentry->d_parent;
+ }
+ memset(s, '\0', sizeof s);
+ strncpy(s, dentry->d_parent->d_name.name, sizeof s - 1);
+ strncat(fullname, strrvs(s), sizeof fullname - 1);
+ strrvs(fullname);
+ } else
+ strncpy(fullname, filename, sizeof fullname - 1);
+ p = strrchr(fullname, '/');
+ *p = '\0';
+ p = strstr(s1, fullname);
+ if (p && p[strlen(fullname)] == ';' && !strstr(s2, current->comm)){
+ printk("%s:%d, %s, %s, %s, %s\n", __FILE__, __LINE__, current-
>comm, fullname, s2, s1);
+ return -EPERM;
+ }
if (!IS_ERR(tmp)) {
fd = get_unused_fd();
diff -uprN linux-2.6.18.orig/include/linux/sysctl.h linux-2.6.18/
include/linux/sysctl.h
--- linux-2.6.18.orig/include/linux/sysctl.h 2009-12-01
16:20:12.000000000 +0800
+++ linux-2.6.18/include/linux/sysctl.h 2009-12-03 09:33:06.000000000
+0800
@@ -794,6 +794,8 @@ enum
FS_AIO_NR=18, /* current system-wide number of aio requests */
FS_AIO_MAX_NR=19, /* system-wide maximum number of aio requests */
FS_INOTIFY=20, /* inotify submenu */
+ FS_UIT_WDSK_ACCESS_APP=21, /* UIT WDSK access app */
+ FS_UIT_WDSK_ACCESS_PTH=22, /* UIT WDSK access pth */
};
/* /proc/sys/fs/quota/ */
diff -uprN linux-2.6.18.orig/kernel/sysctl.c linux-2.6.18/kernel/
sysctl.c
--- linux-2.6.18.orig/kernel/sysctl.c 2009-12-01 16:20:11.000000000
+0800
+++ linux-2.6.18/kernel/sysctl.c 2009-12-03 09:32:06.000000000 +0800
@@ -162,6 +162,10 @@ extern ctl_table inotify_table[];
int sysctl_legacy_va_layout;
#endif
+/* UIT WDSK access */
+extern char fs_uit_wdsk_access_app[];
+extern char fs_uit_wdsk_access_pth[];
+
/* /proc declarations: */
#ifdef CONFIG_PROC_FS
@@ -1030,6 +1034,24 @@ static ctl_table fs_table[] = {
.mode = 0644,
.proc_handler = &proc_dointvec,
},
+ {
+ .ctl_name = FS_UIT_WDSK_ACCESS_APP,
+ .procname = "wdsk_app",
+ .data = fs_uit_wdsk_access_app,
+ .maxlen = 1024 - 1,
+ .mode = 0644,
+ .proc_handler = &proc_dostring,
+ .strategy = &sysctl_string,
+ },
+ {
+ .ctl_name = FS_UIT_WDSK_ACCESS_PTH,
+ .procname = "wdsk_pth",
+ .data = fs_uit_wdsk_access_pth,
+ .maxlen = 1024 - 1,
+ .mode = 0644,
+ .proc_handler = &proc_dostring,
+ .strategy = &sysctl_string,
+ },
#ifdef CONFIG_DNOTIFY
{
.ctl_name = FS_DIR_NOTIFY,