* Physically create a control group in kernel. The group is created in all
* hierarchies, which cover controllers added by cgroup_add_controller().
* All parameters set by cgroup_add_value_* functions are written.
- * The created groups has owner which was set by cgroup_set_uid_gid().
+ * The created groups has owner which was set by cgroup_set_uid_gid() and
+ * permissions set by cgroup_set_permissions.
* @param cgroup
* @param ignore_ownership When nozero, all errors are ignored when setting
* owner of the group and/or its tasks file.
int cgroup_get_uid_gid(struct cgroup *cgroup, uid_t *tasks_uid,
gid_t *tasks_gid, uid_t *control_uid, gid_t *control_gid);
+/**
+ * Stores given file permissions of the group's control and tasks files
+ * into the @c cgroup data structure. Use NO_PERMS if permissions shouldn't
+ * be changed or a value which applicable to chmod(2). Please note that
+ * the given permissions are masked with the file owner's permissions.
+ * For example if a control file has permissions 640 and control_fperm is
+ * 471 the result will be 460.
+ * @param cgroup
+ * @param control_dperm Directory permission for the group.
+ * @param control_fperm File permission for the control files.
+ * @param task_fperm File permissions for task file.
+ */
+void cgroup_set_permissions(struct cgroup *cgroup,
+ mode_t control_dperm, mode_t control_fperm,
+ mode_t task_fperm);
+
/**
* @}
* @name Group parameters
return ret;
}
+int cg_chmod_path(const char *path, mode_t mode, int owner_is_umask)
+{
+ struct stat buf;
+ mode_t mask = -1U;
+
+ if (owner_is_umask) {
+ mode_t umask, gmask, omask;
+
+ /*
+ * Use owner permissions as an umask for group and others
+ * permissions because we trust kernel to initialize owner
+ * permissions to something useful.
+ */
+ if (stat(path, &buf) == -1)
+ goto fail;
+ umask = S_IRWXU & buf.st_mode;
+ gmask = umask >> 3;
+ omask = gmask >> 3;
+
+ mask = umask|gmask|omask;
+ }
+
+ if (chmod(path, mode & mask))
+ goto fail;
+
+ return 0;
+
+fail:
+ last_errno = errno;
+ return ECGOTHER;
+}
+
int cg_chmod_file(FTS *fts, FTSENT *ent, mode_t dir_mode,
- int dirm_change, mode_t file_mode, int filem_change)
+ int dirm_change, mode_t file_mode, int filem_change,
+ int owner_is_umask)
{
int ret = 0;
const char *filename = fts->fts_path;
+
cgroup_dbg("chmod: seeing file %s\n", filename);
+
switch (ent->fts_info) {
case FTS_ERR:
errno = ent->fts_errno;
case FTS_DNR:
case FTS_DP:
if (dirm_change)
- ret = chmod(filename, dir_mode);
+ ret = cg_chmod_path(filename, dir_mode, owner_is_umask);
break;
case FTS_F:
case FTS_NSOK:
case FTS_NS:
case FTS_DEFAULT:
if (filem_change)
- ret = chmod(filename, file_mode);
+ ret = cg_chmod_path(filename, file_mode,
+ owner_is_umask);
break;
}
- if (ret < 0) {
- last_errno = errno;
- ret = ECGOTHER;
- }
return ret;
}
* TODO: Need to decide a better place to put this function.
*/
static int cg_chmod_recursive_controller(char *path, mode_t dir_mode,
- int dirm_change, mode_t file_mode, int filem_change)
+ int dirm_change, mode_t file_mode, int filem_change,
+ int owner_is_umask)
{
int ret = 0;
int final_ret =0;
break;
}
ret = cg_chmod_file(fts, ent, dir_mode, dirm_change,
- file_mode, filem_change);
+ file_mode, filem_change, owner_is_umask);
if (ret) {
last_errno = errno;
final_ret = ECGOTHER;
break;
}
ret = cg_chmod_recursive_controller(path, dir_mode, dirm_change,
- file_mode, filem_change);
+ file_mode, filem_change, 0);
if (ret)
final_ret = ret;
}
return final_ret;
}
+void cgroup_set_permissions(struct cgroup *cgroup,
+ mode_t control_dperm, mode_t control_fperm,
+ mode_t task_fperm)
+{
+ cgroup->control_dperm = control_dperm;
+ cgroup->control_fperm = control_fperm;
+ cgroup->task_fperm = task_fperm;
+}
+
static char *cgroup_basename(const char *path)
{
char *base;
cgroup_dbg("Changing ownership of %s\n", fts_path[0]);
error = cg_chown_recursive(fts_path,
cgroup->control_uid, cgroup->control_gid);
- if (!error) {
+ if (!error)
error = cg_chmod_recursive_controller(fts_path[0],
cgroup->control_dperm,
cgroup->control_dperm != NO_PERMS,
cgroup->control_fperm,
- cgroup->control_fperm != NO_PERMS);
- }
+ cgroup->control_fperm != NO_PERMS,
+ 1);
}
if (error)
error = chown(path, cgroup->tasks_uid,
cgroup->tasks_gid);
if (!error && cgroup->task_fperm != NO_PERMS)
- error = chmod(path, cgroup->task_fperm);
+ error = cg_chmod_path(path, cgroup->task_fperm,
+ 1);
if (error) {
last_errno = errno;
}
/* all variables set so create cgroup */
+ if (dirm_change + filem_change > 0)
+ cgroup_set_permissions(cgroup, dir_mode, file_mode,
+ file_mode);
ret = cgroup_create_cgroup(cgroup, 0);
if (ret) {
fprintf(stderr, "%s: "
cgroup_free(&cgroup);
goto err;
}
- if (dirm_change + filem_change > 0) {
- ret = cg_chmod_recursive(cgroup, dir_mode, dirm_change,
- file_mode, filem_change);
- if (ret) {
- fprintf(stderr, "%s: can't change permission " \
- "of cgroup %s: %s\n", argv[0],
- cgroup->name, cgroup_strerror(ret));
- cgroup_free(&cgroup);
- goto err;
- }
- }
cgroup_free(&cgroup);
}
err: