[Kimchi-devel] [PATCH V7] add a method to fix search permissions

Sheldon shaohef at linux.vnet.ibm.com
Thu Jan 9 14:06:53 UTC 2014


On 01/09/2014 03:25 PM, Royce Lv wrote:
> On 2014年01月09日 08:01, shaohef at linux.vnet.ibm.com wrote:
>> From: ShaoHe Feng <shaohef at linux.vnet.ibm.com>
>>
>> First will use setfacl to set the path search permission for user or
>> group, if failed then set search permission for others on the path.
>>
>> Usage:
>> check_path_permission("/tmp/need/to/fix/path", username)
>> fix_path_permission("/tmp/need/to/fix/path", username)
>>
>> Signed-off-by: ShaoHe Feng <shaohef at linux.vnet.ibm.com>
>> Signed-off-by: Aline Manera <alinefm at linux.vnet.ibm.com>
>> Signed-off-by: Royce Lv <lvroyce at linux.vnet.ibm.com>
>> ---
>>   Makefile.am         |   1 +
>>   src/kimchi/utils.py | 122 
>> +++++++++++++++++++++++++++++++++++++++++++++++++++-
>>   2 files changed, 122 insertions(+), 1 deletion(-)
>>
>> diff --git a/Makefile.am b/Makefile.am
>> index 04ad696..1f80e5f 100644
>> --- a/Makefile.am
>> +++ b/Makefile.am
>> @@ -46,6 +46,7 @@ PEP8_WHITELIST = \
>>       src/kimchi/cachebust.py \
>>       src/kimchi/config.py.in \
>>       src/kimchi/control/*.py \
>> +    src/kimchi/utils.py \
>>       src/kimchi/disks.py \
>>       src/kimchi/distroloader.py \
>>       src/kimchi/exception.py \
>> diff --git a/src/kimchi/utils.py b/src/kimchi/utils.py
>> index af245c6..62a412d 100644
>> --- a/src/kimchi/utils.py
>> +++ b/src/kimchi/utils.py
>> @@ -18,11 +18,16 @@
>>   #
>>   # You should have received a copy of the GNU Lesser General Public
>>   # License along with this library; if not, write to the Free Software
>> -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
>> 02110-1301  USA
>> +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
>> 02110-1301 USA
>>   #
>>
>>   import cherrypy
>> +import grp
>>   import os
>> +import pwd
>> +import re
>> +import stat
>> +import subprocess
>>   import urllib2
>>
>>
>> @@ -34,6 +39,7 @@ from kimchi import config
>>
>>   kimchi_log = cherrypy.log.error_log
>>
>> +
>>   def is_digit(value):
>>       if isinstance(value, int):
>>           return True
>> @@ -96,3 +102,117 @@ def check_url_path(path):
>>           return False
>>
>>       return True
>> +
>> +
>> +def run_command(cmd):
>> +    try:
>> +        proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
>> +                                stderr=subprocess.PIPE)
>> +        out, error = proc.communicate()
> As this command will be used at multiple cases, we may not want to 
> wait the execute result,  do you think it's reasonable to add a 
> timeout here?
ACK. we need a synchronous run_command with timeout.
>> +
>> +        kimchi_log.debug("Run command '%s'", " ".join(cmd))
>> +        if out or error:
>> +            kimchi_log.debug("out:\n %s\nerror:\n %s", out, error)
>> +    except OSError as e:
>> +        kimchi_log.error("Failed to run command %s. %s", " ".join(cmd),
>> +                         e.message)
>> +        return (None, None, None)
> I think according to 
> http://docs.python.org/3.3/library/subprocess.html#exceptions:
> Multiple exceptions will be raised and just except OSError may leak 
> others.
> What about except all?
ACK
>
>> +    if proc.returncode != 0:
>> +        kimchi_log.debug("Cmd '%s' failed, error code: %s", cmd, error)
>> +    return (out, error, proc.returncode)
>> +
>> +
>> +def name_uid(user):
>> +    return pwd.getpwnam(user).pw_uid
>> +
>> +
>> +def get_group_ids(user):
>> +    gids = [g.gr_gid for g in grp.getgrall() if user in g.gr_mem]
>> +    gid = pwd.getpwnam(user).pw_gid
>> +    gids.append(grp.getgrgid(gid).gr_gid)
>> +    return gids
>> +
>> +
>> +def get_groups(user):
>> +    gids = get_group_ids(user)
>> +    return [grp.getgrgid(gid).gr_name for gid in gids]
>> +
>> +
>> +def run_setfacl_set_x(path, user="qemu"):
>> +    set_user = ["setfacl", "--modify", "user:%s:x" % user, path]
>> +    out, error, ret = run_command(set_user)
>> +    return ret == 0
>> +
>> +
>> +def run_getfacl(path, user="qemu", groups=[]):
>> +    cmd = ["getfacl", path]
>> +    out, error, ret = run_command(cmd)
>> +    if out and ret == 0:
>> +        res = re.findall("user:%s:..x" % user, out)
>> +        if res:
>> +            return True
>> +        res = re.findall("(?<=group:)(.*)(?=:..x)",
>> +                         out) if groups else []
>> +        return list(set(res) & set(groups)) != []
>> +    return False
>> +
>> +
>> +def set_x_on_path(path, who="other"):
>> +    S_IXWHO = ((stat.S_IXUSR if who == "user" else None) or
>> +               (stat.S_IXGRP if who == "group" else None) or
>> +               stat.S_IXOTH)
>> +    mode = os.stat(path).st_mode | S_IXWHO
>> +    os.chmod(path, mode)
>> +    ret = os.stat(path).st_mode == mode
>> +    if not ret:
>> +        kimchi_log.debug("faild to set +x attribute on %s", path)
>> +    return ret
>> +
>> +
>> +def get_x_on_path(path, uid, gids=[]):
>> +    try:
>> +        st = os.stat(path)
>> +        mode = st.st_mode
>> +        return ((uid == st.st_uid and mode & stat.S_IXUSR == 
>> stat.S_IXUSR) or
>> +                (st.st_gid in gids and mode & stat.S_IXGRP == 
>> stat.S_IXGRP) or
>> +                mode & stat.S_IXOTH == stat.S_IXOTH)
>> +    except OSError as e:
>> +        kimchi_log.error("faild to get attribute on %s as user id: 
>> %s. %s",
>> +                         path, uid, e.message)
>> +        return False
>> +
>> +
>> +def check_path_permission(path, user='qemu', groups=[]):
>> +    groups = groups if groups else get_groups(user)
>> +    gids = [grp.getgrnam(group).gr_gid for group in groups] if 
>> groups else []
>> +    path = os.path.abspath(path)
>> +    paths = path.split("/")
>> +    paths = paths[1:]
>> +    path = "/"
>> +    for p in paths:
>> +        path = os.path.join(path, p)
>> +        if not (get_x_on_path(path, name_uid(user), gids) or
>> +                run_getfacl(path, user, groups)):
>> +            return False
>> +    return True
>> +
>> +
>> +def fix_path_permission(path, user='qemu', groups=[]):
>> +    groups = groups if groups else get_groups(user)
>> +    gids = [grp.getgrnam(group).gr_gid for group in groups] if 
>> groups else []
>> +    path = os.path.abspath(path)
>> +    paths = path.split("/")
>> +    paths = paths[1:]
>> +    path = "/"
>> +    for p in paths:
>> +        path = os.path.join(path, p)
>> +        st = os.stat(path)
>> +        uid = name_uid(user)
>> +        who = 'user' if st.st_uid == uid else None
>> +        who = 'group' if not who and st.st_gid in gids else 'other'
>> +        if not (get_x_on_path(path, uid, gids) or
>> +                run_getfacl(path, user, groups) or
>> +                run_setfacl_set_x(path, user) or
>> +                set_x_on_path(path, who)):
>> +            return False
>> +    return True
>
>
>


-- 
Thanks and best regards!

Sheldon Feng(冯少合)<shaohef at linux.vnet.ibm.com>
IBM Linux Technology Center




More information about the Kimchi-devel mailing list