
From: ShaoHe Feng <shaohef@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@linux.vnet.ibm.com> Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/utils.py | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 1 deletion(-) diff --git a/src/kimchi/utils.py b/src/kimchi/utils.py index f7eda93..daf5c8d 100644 --- a/src/kimchi/utils.py +++ b/src/kimchi/utils.py @@ -18,11 +18,15 @@ # # 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 os +import pwd +import re +import stat +import subprocess from cherrypy.lib.reprconf import Parser @@ -33,6 +37,7 @@ from kimchi import config kimchi_log = cherrypy.log.error_log + def is_digit(value): if isinstance(value, int): return True @@ -84,3 +89,112 @@ def import_class(class_path): def import_module(module_name): return __import__(module_name, fromlist=['']) + + +def name_uid(user): + return pwd.getpwnam(user).pw_uid + + +def run_command(cmd): + try: + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + out, error = proc.communicate() + + 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: + kimchi_log.debug("Failed to run command %s", " ".join(cmd)) + return (None, None, None) + if proc.returncode != 0: + kimchi_log.debug("Cmd '%s' failed, error code: %s", cmd, error) + return (out, error, proc.returncode) + + +def run_setfacl_set_x(path, user="qemu", group=None): + set_user = ["setfacl", "--modify", "user:%s:x" % user, path] + set_group = ["setfacl", "--modify", "group:%s:x" % group, path] + out, error, ret = run_command(set_user) + if ret != 0 and group: + out, error, ret = run_command(set_group) + return ret == 0 + + +def run_getfacl(path, user="qemu", group=None): + cmd = ["getfacl", path] + out, error, ret = run_command(cmd) + if out and ret == 0: + res = re.findall("user:%s:..x" % user, out) + res = re.findall("group:%s:..x" % group, + out) if group and not res else res + return res != [] + 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): + try: + info = os.stat(path) + mode = info.st_mode + return ((uid == info.st_uid and mode & stat.S_IXUSR == stat.S_IXUSR) or + (uid == info.st_gid and mode & stat.S_IXGRP == stat.S_IXGRP) or + mode & stat.S_IXGRP == stat.S_IXOTH) + except OSError: + kimchi_log.debug("faild to get attribute on %s as user id: %s", + path, uid) + return False + + +def check_path_permission(path, user='qemu', group=None): + return get_x_on_path(path, + name_uid(user)) or run_getfacl(path, user, group) + + +def fix_path_permission(path, user='qemu'): + paths = [] + while path: + paths.append(path) + if path == "/": + break + path = os.path.dirname(path) + + paths.reverse() + for path in paths: + if not (check_path_permission(path) or + run_setfacl_set_x(path) or + set_x_on_path(path)): + return False + return True + + +def check_path_acl_permission(path, user='qemu', group=None): + return run_getfacl(path, user, group) + + +def fix_path_acl_permission(path, user='qemu'): + paths = [] + while path: + paths.append(path) + if path == "/": + break + path = os.path.dirname(path) + + paths.reverse() + for path in paths: + if not (run_getfacl(path, user) or run_setfacl_set_x(path, user)): + kimchi_log.debug("faild to set on researchable permission on %s " + "for user: %s", path, user) + return False + return True -- 1.8.4.2