port-solaris.c revision 221420
1139749Simp/* $Id: port-solaris.c,v 1.4 2010/11/05 01:03:05 dtucker Exp $ */
2119853Scg
350724Scg/*
450724Scg * Copyright (c) 2006 Chad Mynhier.
550724Scg *
650724Scg * Permission to use, copy, modify, and distribute this software for any
750724Scg * purpose with or without fee is hereby granted, provided that the above
850724Scg * copyright notice and this permission notice appear in all copies.
950724Scg *
1050724Scg * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1150724Scg * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1250724Scg * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1350724Scg * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1450724Scg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1550724Scg * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1650724Scg * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1750724Scg */
1850724Scg
1950724Scg#include "config.h"
2050724Scg#include "includes.h"
2150724Scg
2250724Scg#ifdef USE_SOLARIS_PROCESS_CONTRACTS
2350724Scg
2450724Scg#include <sys/types.h>
2550724Scg#include <sys/stat.h>
2650724Scg#include <sys/param.h>
2753465Scg
2850724Scg#include <errno.h>
2970134Scg#ifdef HAVE_FCNTL_H
3070134Scg# include <fcntl.h>
3182180Scg#endif
3282180Scg#include <stdarg.h>
3370134Scg#include <string.h>
3470134Scg#include <unistd.h>
3566308Scg
3665645Scg#include <libcontract.h>
3750724Scg#include <sys/contract/process.h>
38164614Sariff#include <sys/ctfs.h>
39164614Sariff
40167644Sariff#include "log.h"
41167644Sariff
42167644Sariff#define CT_TEMPLATE	CTFS_ROOT "/process/template"
43167644Sariff#define CT_LATEST	CTFS_ROOT "/process/latest"
44167644Sariff
45167644Sariffstatic int tmpl_fd = -1;
46167644Sariff
47167644Sariff/* Lookup the latest process contract */
48170289Sdwmalonestatic ctid_t
49167644Sariffget_active_process_contract_id(void)
50167644Sariff{
51167644Sariff	int stat_fd;
52167644Sariff	ctid_t ctid = -1;
53167644Sariff	ct_stathdl_t stathdl;
54167644Sariff
55167644Sariff	if ((stat_fd = open64(CT_LATEST, O_RDONLY)) == -1) {
56167644Sariff		error("%s: Error opening 'latest' process "
57167644Sariff		    "contract: %s", __func__, strerror(errno));
58167644Sariff		return -1;
59167644Sariff	}
60167644Sariff	if (ct_status_read(stat_fd, CTD_COMMON, &stathdl) != 0) {
61167644Sariff		error("%s: Error reading process contract "
62167644Sariff		    "status: %s", __func__, strerror(errno));
63167644Sariff		goto out;
64167644Sariff	}
65167644Sariff	if ((ctid = ct_status_get_id(stathdl)) < 0) {
66167644Sariff		error("%s: Error getting process contract id: %s",
67167644Sariff		    __func__, strerror(errno));
68167644Sariff		goto out;
69167644Sariff	}
70167644Sariff
71164614Sariff	ct_status_free(stathdl);
72164614Sariff out:
73167644Sariff	close(stat_fd);
74164614Sariff	return ctid;
7564881Scg}
7664881Scg
7770134Scgvoid
7864881Scgsolaris_contract_pre_fork(void)
7964881Scg{
8064881Scg	if ((tmpl_fd = open64(CT_TEMPLATE, O_RDWR)) == -1) {
8164881Scg		error("%s: open %s: %s", __func__,
8264881Scg		    CT_TEMPLATE, strerror(errno));
8364881Scg		return;
8450724Scg	}
8550724Scg
8664881Scg	debug2("%s: setting up process contract template on fd %d",
8764881Scg	    __func__, tmpl_fd);
8864881Scg
8989834Scg	/* First we set the template parameters and event sets. */
9089834Scg	if (ct_pr_tmpl_set_param(tmpl_fd, CT_PR_PGRPONLY) != 0) {
9170134Scg		error("%s: Error setting process contract parameter set "
9264881Scg		    "(pgrponly): %s", __func__, strerror(errno));
9364881Scg		goto fail;
9464881Scg	}
9564881Scg	if (ct_pr_tmpl_set_fatal(tmpl_fd, CT_PR_EV_HWERR) != 0) {
9689834Scg		error("%s: Error setting process contract template "
9789834Scg		    "fatal events: %s", __func__, strerror(errno));
9864881Scg		goto fail;
99111909Sorion	}
10089834Scg	if (ct_tmpl_set_critical(tmpl_fd, 0) != 0) {
10197274Sbde		error("%s: Error setting process contract template "
10297274Sbde		    "critical events: %s", __func__, strerror(errno));
10389834Scg		goto fail;
10489834Scg	}
10589834Scg	if (ct_tmpl_set_informative(tmpl_fd, CT_PR_EV_HWERR) != 0) {
10670134Scg		error("%s: Error setting process contract template "
10764881Scg		    "informative events: %s", __func__, strerror(errno));
10864881Scg		goto fail;
10964881Scg	}
11064881Scg
11189834Scg	/* Now make this the active template for this process. */
112164614Sariff	if (ct_tmpl_activate(tmpl_fd) != 0) {
113164614Sariff		error("%s: Error activating process contract "
114170161Sariff		    "template: %s", __func__, strerror(errno));
115164614Sariff		goto fail;
116164614Sariff	}
117170161Sariff	return;
118170161Sariff
119170161Sariff fail:
120170884Sariff	if (tmpl_fd != -1) {
121164614Sariff		close(tmpl_fd);
122164614Sariff		tmpl_fd = -1;
123164614Sariff	}
124164614Sariff}
125164614Sariff
126164614Sariffvoid
127164614Sariffsolaris_contract_post_fork_child()
128164614Sariff{
129164614Sariff	debug2("%s: clearing process contract template on fd %d",
130164614Sariff	    __func__, tmpl_fd);
131164614Sariff
132164614Sariff	/* Clear the active template. */
133164614Sariff	if (ct_tmpl_clear(tmpl_fd) != 0)
134164614Sariff		error("%s: Error clearing active process contract "
135164614Sariff		    "template: %s", __func__, strerror(errno));
136164614Sariff
137164614Sariff	close(tmpl_fd);
138164614Sariff	tmpl_fd = -1;
139164614Sariff}
140164614Sariff
141164614Sariffvoid
142164614Sariffsolaris_contract_post_fork_parent(pid_t pid)
143164614Sariff{
144164614Sariff	ctid_t ctid;
145164614Sariff	char ctl_path[256];
146164614Sariff	int r, ctl_fd = -1, stat_fd = -1;
147164614Sariff
148164614Sariff	debug2("%s: clearing template (fd %d)", __func__, tmpl_fd);
149164614Sariff
150164614Sariff	if (tmpl_fd == -1)
151164614Sariff		return;
152164614Sariff
153164614Sariff	/* First clear the active template. */
154164614Sariff	if ((r = ct_tmpl_clear(tmpl_fd)) != 0)
155164614Sariff		error("%s: Error clearing active process contract "
156164614Sariff		    "template: %s", __func__, strerror(errno));
157164614Sariff
158164614Sariff	close(tmpl_fd);
159164614Sariff	tmpl_fd = -1;
160164614Sariff
16189834Scg	/*
16289834Scg	 * If either the fork didn't succeed (pid < 0), or clearing
16389834Scg	 * th active contract failed (r != 0), then we have nothing
16464881Scg	 * more do.
16564881Scg	 */
16664881Scg	if (r != 0 || pid <= 0)
16789834Scg		return;
16889834Scg
16989834Scg	/* Now lookup and abandon the contract we've created. */
17064881Scg	ctid = get_active_process_contract_id();
17170134Scg
17275355Scg	debug2("%s: abandoning contract id %ld", __func__, ctid);
173111909Sorion
17489834Scg	snprintf(ctl_path, sizeof(ctl_path),
17589834Scg	    CTFS_ROOT "/process/%ld/ctl", ctid);
17689834Scg	if ((ctl_fd = open64(ctl_path, O_WRONLY)) < 0) {
17789834Scg		error("%s: Error opening process contract "
17889834Scg		    "ctl file: %s", __func__, strerror(errno));
17970134Scg		goto fail;
18070134Scg	}
18164881Scg	if (ct_ctl_abandon(ctl_fd) < 0) {
18264881Scg		error("%s: Error abandoning process contract: %s",
18364881Scg		    __func__, strerror(errno));
18464881Scg		goto fail;
18564881Scg	}
18664881Scg	close(ctl_fd);
18764881Scg	return;
18889834Scg
18964881Scg fail:
19064881Scg	if (tmpl_fd != -1) {
19174363Scg		close(tmpl_fd);
19274363Scg		tmpl_fd = -1;
19374363Scg	}
19474363Scg	if (stat_fd != -1)
19574363Scg		close(stat_fd);
19674363Scg	if (ctl_fd != -1)
19774363Scg		close(ctl_fd);
19874363Scg}
19974363Scg#endif
20074363Scg
20174363Scg#ifdef USE_SOLARIS_PROJECTS
20274363Scg#include <sys/task.h>
20374363Scg#include <project.h>
20450724Scg
20564881Scg/*
20650724Scg * Get/set solaris default project.
20766308Scg * If we fail, just run along gracefully.
20866308Scg */
20966308Scgvoid
21066308Scgsolaris_set_default_project(struct passwd *pw)
21150724Scg{
21250724Scg	struct project  *defaultproject;
21370134Scg	struct project   tempproject;
21474763Scg	char buf[1024];
21550724Scg
21670134Scg	/* get default project, if we fail just return gracefully  */
21770134Scg	if ((defaultproject = getdefaultproj(pw->pw_name, &tempproject, &buf,
21870134Scg	    sizeof(buf))) > 0) {
21964881Scg		/* set default project */
22074763Scg		if (setproject(defaultproject->pj_name, pw->pw_name,
22170134Scg		    TASK_NORMAL) != 0)
22270134Scg			debug("setproject(%s): %s", defaultproject->pj_name,
22374763Scg			    strerror(errno));
22470134Scg	} else {
22570134Scg		/* debug on getdefaultproj() error */
226111909Sorion		debug("getdefaultproj(%s): %s", pw->pw_name, strerror(errno));
22789834Scg	}
22889834Scg}
22989834Scg#endif /* USE_SOLARIS_PROJECTS */
23070134Scg