2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
20 #include <security/pam_ext.h>
21 #include <security/pam_modules.h>
27 #include "krate-builder.h"
29 #include <klay/cgroup.h>
30 #include <klay/namespace.h>
31 #include <klay/exception.h>
32 #include <klay/filesystem.h>
33 #include <klay/xml/parser.h>
34 #include <klay/xml/document.h>
36 #define CGROUP_SUBSYSTEM "krate"
38 #define KRATE_UID_MIN 6000
39 #define KRATE_UID_MAX 6999
41 #define LAZYMOUNT_EXTERN extern
42 #define LAZYMOUNT_LIB "/usr/lib/liblazymount.so.0"
44 std::string buildKrateManifestPath(const std::string& name)
46 return "/home/" + name + "/.config/krate/krate.xml";
49 std::string getKrateName(pam_handle_t* handle)
52 int error = ::pam_get_item(handle, PAM_USER, &retItem);
53 if (error != PAM_SUCCESS) {
54 throw runtime::Exception("Failed to get user");
57 return static_cast<const char*>(retItem);
60 void enterKrate(const std::string& name)
62 std::string path = CGROUP_SUBSYSTEM "/" + name;
65 if (runtime::Cgroup::exist(CGROUP_SUBSYSTEM, path)) {
66 auto pids = runtime::Cgroup::getProcessList(CGROUP_SUBSYSTEM, path);
67 if (pids.size() > 0) {
71 runtime::Cgroup::create(CGROUP_SUBSYSTEM, path);
75 runtime::Cgroup::addProcess(CGROUP_SUBSYSTEM, path, ::getpid());
76 runtime::Namespace::unshare(CLONE_NEWNS | CLONE_NEWIPC);
78 runtime::Namespace::attach(pid);
82 static int wait_condition(void)
87 int (*wait_mount_user)(void);
89 r = access(LAZYMOUNT_LIB, F_OK);
91 fprintf(stderr, "cannot find lazymount module - No support lazymount\n");
95 h = dlopen(LAZYMOUNT_LIB, RTLD_LAZY);
97 fprintf(stderr, "lazymount module dlopen error\n");
102 wait_mount_user = (int (*)())dlsym(h, "wait_mount_user");
103 if (!wait_mount_user) {
104 fprintf(stderr, "dlsym wait_mount_user error\n");
110 r = wait_mount_user();
112 fprintf(stderr, "wait_mout_user failed\n");
122 LAZYMOUNT_EXTERN __attribute__((visibility("default")))
123 int container_preprocess(char* id) {
124 std::cout << "kraterize (UID " << id << ")..." << std::endl << std::flush;
126 runtime::User user(std::stoi(std::string(id)));
128 enterKrate(user.getName());
130 if (user.getUid() >= KRATE_UID_MIN && user.getUid() <= KRATE_UID_MAX ) {
133 } catch (runtime::Exception& e) {
134 std::cerr << "krate error : " << e.what() <<std::endl << std::flush;
138 std::cout << "krate preprocess completed!" << std::endl << std::flush;
142 LAZYMOUNT_EXTERN __attribute__((visibility("default")))
143 int container_postprocess(char* id) {
145 runtime::User user(std::stoi(std::string(id)));
146 KrateBuilder builder(user, buildKrateManifestPath(user.getName()));
147 builder.mountOwnFilesystem();
148 } catch (runtime::Exception& e) {
149 std::cerr << "krate error : " << e.what() << std::endl << std::flush;
152 std::cout << "krate postprocess completed!" << std::endl << std::flush;
153 std::cout << "kraterized!" << std::endl << std::flush;
157 PAM_EXTERN __attribute__((visibility("default")))
158 int pam_sm_open_session(pam_handle_t* pamh, int flags, int argc, const char* argv[])
161 runtime::User user(getKrateName(pamh));
163 enterKrate(user.getName());
165 KrateBuilder builder(user, buildKrateManifestPath(user.getName()));
166 builder.mountOwnFilesystem();
167 } catch (runtime::Exception& e) {
168 ::pam_syslog(pamh, LOG_ERR, "%s", e.what());
169 return PAM_SESSION_ERR;
175 PAM_EXTERN __attribute__((visibility("default")))
176 int pam_sm_close_session(pam_handle_t* pamh, int flags, int argc, const char* argv[])
179 std::string name = getKrateName(pamh);
180 auto pids = runtime::Cgroup::getProcessList(CGROUP_SUBSYSTEM, name);
181 if (pids.size() <= 1) {
182 std::string path = CGROUP_SUBSYSTEM "/" + name;
183 runtime::Cgroup::destroy(CGROUP_SUBSYSTEM, path);
185 } catch (runtime::Exception& e) {
186 ::pam_syslog(pamh, LOG_ERR, "%s", e.what());
187 return PAM_SESSION_ERR;
193 #ifdef PAM_MODULE_ENTRY
194 PAM_MODULE_ENTRY("pam_krate");