[launchd-changes] [23870] trunk
source_changes at macosforge.org
source_changes at macosforge.org
Thu Mar 26 00:22:22 PDT 2009
Revision: 23870
http://trac.macosforge.org/projects/launchd/changeset/23870
Author: dsorresso at apple.com
Date: 2009-03-26 00:22:22 -0700 (Thu, 26 Mar 2009)
Log Message:
-----------
<rdar://problem/6718433>
Modified Paths:
--------------
trunk/launchd/src/launch_priv.h
trunk/launchd/src/launchd.c
trunk/launchd/src/launchd_core_logic.c
trunk/launchd/src/launchd_runtime.c
trunk/launchd/src/launchd_unix_ipc.c
trunk/launchd/src/liblaunch.c
trunk/launchd.xcodeproj/project.pbxproj
Modified: trunk/launchd/src/launch_priv.h
===================================================================
--- trunk/launchd/src/launch_priv.h 2009-03-25 21:52:29 UTC (rev 23869)
+++ trunk/launchd/src/launch_priv.h 2009-03-26 07:22:22 UTC (rev 23870)
@@ -78,7 +78,7 @@
typedef struct _launch *launch_t;
-launch_t launchd_fdopen(int);
+launch_t launchd_fdopen(int, int);
int launchd_getfd(launch_t);
void launchd_close(launch_t, __typeof__(close) closefunc);
Modified: trunk/launchd/src/launchd.c
===================================================================
--- trunk/launchd/src/launchd.c 2009-03-25 21:52:29 UTC (rev 23869)
+++ trunk/launchd/src/launchd.c 2009-03-26 07:22:22 UTC (rev 23870)
@@ -231,6 +231,7 @@
pthread_t t = NULL;
int err = pthread_create(&t, NULL, update_thread, NULL);
launchd_assumes(err == 0);
+ launchd_assumes(pthread_detach(t) == 0);
}
jobmgr_init(sflag);
Modified: trunk/launchd/src/launchd_core_logic.c
===================================================================
--- trunk/launchd/src/launchd_core_logic.c 2009-03-25 21:52:29 UTC (rev 23869)
+++ trunk/launchd/src/launchd_core_logic.c 2009-03-26 07:22:22 UTC (rev 23870)
@@ -4327,7 +4327,9 @@
bool log_to_console = pri & LOG_CONSOLE;
int _pri = pri & ~LOG_CONSOLE;
- struct runtime_syslog_attr attr = { g_my_label, j->label, j->mgr->name, _pri, getuid(), getpid(), j->p };
+ const char *label2use = j ? j->label : "com.apple.launchd.NULL";
+ const char *mgr2use = j ? j->mgr->name : "NULL";
+ struct runtime_syslog_attr attr = { g_my_label, label2use, mgr2use, _pri, getuid(), getpid(), j ? j->p : 0 };
char *newmsg;
int oldmask = 0;
size_t newmsgsz;
@@ -4348,23 +4350,23 @@
#if !TARGET_OS_EMBEDDED
snprintf(newmsg, newmsgsz, "%s: %s", msg, strerror(err));
#else
- snprintf(newmsg, newmsgsz, "(%s) %s: %s", j->label, msg, strerror(err));
+ snprintf(newmsg, newmsgsz, "(%s) %s: %s", label2use, msg, strerror(err));
#endif
} else {
#if !TARGET_OS_EMBEDDED
snprintf(newmsg, newmsgsz, "%s", msg);
#else
- snprintf(newmsg, newmsgsz, "(%s) %s", j->label, msg);
+ snprintf(newmsg, newmsgsz, "(%s) %s", label2use, msg);
#endif
}
- if (unlikely(j->debug)) {
+ if( j && unlikely(j->debug) ) {
oldmask = setlogmask(LOG_UPTO(LOG_DEBUG));
}
runtime_vsyslog(&attr, log_to_console, newmsg, ap);
- if (unlikely(j->debug)) {
+ if( j && unlikely(j->debug) ) {
setlogmask(oldmask);
}
}
@@ -6689,6 +6691,12 @@
return BOOTSTRAP_NOT_PRIVILEGED;
}
+#if HAVE_SANDBOX
+ if (unlikely(sandbox_check(ldc->pid, "job-creation", SANDBOX_FILTER_NONE) > 0)) {
+ return BOOTSTRAP_NOT_PRIVILEGED;
+ }
+#endif
+
if (unlikely(!(otherj = job_find(targetlabel)))) {
return BOOTSTRAP_UNKNOWN_SERVICE;
}
@@ -7358,6 +7366,12 @@
return BOOTSTRAP_NOT_PRIVILEGED;
#endif
+#if HAVE_SANDBOX
+ if (unlikely(sandbox_check(ldc->pid, "job-creation", SANDBOX_FILTER_NONE) > 0)) {
+ return BOOTSTRAP_NOT_PRIVILEGED;
+ }
+#endif
+
if (!launchd_assumes(j != NULL)) {
return BOOTSTRAP_NO_MEMORY;
}
Modified: trunk/launchd/src/launchd_runtime.c
===================================================================
--- trunk/launchd/src/launchd_runtime.c 2009-03-25 21:52:29 UTC (rev 23869)
+++ trunk/launchd/src/launchd_runtime.c 2009-03-26 07:22:22 UTC (rev 23870)
@@ -151,7 +151,6 @@
launchd_runtime_init(void)
{
mach_msg_size_t mxmsgsz;
- pthread_attr_t attr;
pid_t p = getpid();
launchd_assert((mainkq = kqueue()) != -1);
@@ -171,13 +170,9 @@
}
launchd_assert(runtime_add_mport(launchd_internal_port, launchd_internal_demux, mxmsgsz) == KERN_SUCCESS);
+ launchd_assert(pthread_create(&kqueue_demand_thread, NULL, kqueue_demand_loop, NULL) == 0);
+ launchd_assert(pthread_detach(kqueue_demand_thread) == 0);
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);
- launchd_assert(pthread_create(&kqueue_demand_thread, &attr, kqueue_demand_loop, NULL) == 0);
- pthread_attr_destroy(&attr);
-
launchd_assumes(sysctlbyname("vfs.generic.noremotehang", NULL, NULL, &p, sizeof(p)) != -1);
}
Modified: trunk/launchd/src/launchd_unix_ipc.c
===================================================================
--- trunk/launchd/src/launchd_unix_ipc.c 2009-03-25 21:52:29 UTC (rev 23869)
+++ trunk/launchd/src/launchd_unix_ipc.c 2009-03-26 07:22:22 UTC (rev 23870)
@@ -186,7 +186,12 @@
fcntl(fd, F_SETFL, O_NONBLOCK);
c->kqconn_callback = ipc_callback;
- c->conn = launchd_fdopen(fd);
+ if( j ) {
+ c->conn = launchd_fdopen(-1, fd);
+ } else {
+ c->conn = launchd_fdopen(fd, -1);
+ }
+
c->j = j;
LIST_INSERT_HEAD(&connections, c, sle);
kevent_mod(fd, EVFILT_READ, EV_ADD, 0, 0, &c->kqconn_callback);
@@ -337,7 +342,6 @@
launch_data_free(rmc.resp);
}
-
void
ipc_readmsg2(launch_data_t data, const char *cmd, void *context)
{
@@ -349,80 +353,85 @@
return;
}
- //job_log(rmc->c->j, LOG_DEBUG, "Unix IPC request: %s", cmd);
-
- if (data == NULL) {
- if (!strcmp(cmd, LAUNCH_KEY_CHECKIN)) {
- if (rmc->c->j) {
- resp = job_export(rmc->c->j);
- job_checkin(rmc->c->j);
- } else {
- resp = launch_data_new_errno(EACCES);
+// job_log(rmc->c->j, LOG_NOTICE, "Socket IPC request: %s.", cmd);
+
+ /* Do not allow commands other than check-in to come over the trusted socket. */
+ if( data == NULL && rmc->c->j ) {
+ if( strcmp(cmd, LAUNCH_KEY_CHECKIN) == 0 ) {
+ resp = job_export(rmc->c->j);
+ job_checkin(rmc->c->j);
+ } else {
+ resp = launch_data_new_errno(EACCES);
+ }
+ } else {
+ if( data == NULL ) {
+ if (!strcmp(cmd, LAUNCH_KEY_SHUTDOWN)) {
+ launchd_shutdown();
+ resp = launch_data_new_errno(0);
+ } else if (!strcmp(cmd, LAUNCH_KEY_SINGLEUSER)) {
+ launchd_single_user();
+ resp = launch_data_new_errno(0);
+ } else if (!strcmp(cmd, LAUNCH_KEY_GETJOBS)) {
+ resp = job_export_all();
+ ipc_revoke_fds(resp);
+ } else if (!strcmp(cmd, LAUNCH_KEY_GETRESOURCELIMITS)) {
+ resp = adjust_rlimits(NULL);
+ } else if (!strcmp(cmd, LAUNCH_KEY_GETRUSAGESELF)) {
+ struct rusage rusage;
+ getrusage(RUSAGE_SELF, &rusage);
+ resp = launch_data_new_opaque(&rusage, sizeof(rusage));
+ } else if (!strcmp(cmd, LAUNCH_KEY_GETRUSAGECHILDREN)) {
+ struct rusage rusage;
+ getrusage(RUSAGE_CHILDREN, &rusage);
+ resp = launch_data_new_opaque(&rusage, sizeof(rusage));
}
- } else if (!strcmp(cmd, LAUNCH_KEY_SHUTDOWN)) {
- launchd_shutdown();
- resp = launch_data_new_errno(0);
- } else if (!strcmp(cmd, LAUNCH_KEY_SINGLEUSER)) {
- launchd_single_user();
- resp = launch_data_new_errno(0);
- } else if (!strcmp(cmd, LAUNCH_KEY_GETJOBS)) {
- resp = job_export_all();
- ipc_revoke_fds(resp);
- } else if (!strcmp(cmd, LAUNCH_KEY_GETRESOURCELIMITS)) {
- resp = adjust_rlimits(NULL);
- } else if (!strcmp(cmd, LAUNCH_KEY_GETRUSAGESELF)) {
- struct rusage rusage;
- getrusage(RUSAGE_SELF, &rusage);
- resp = launch_data_new_opaque(&rusage, sizeof(rusage));
- } else if (!strcmp(cmd, LAUNCH_KEY_GETRUSAGECHILDREN)) {
- struct rusage rusage;
- getrusage(RUSAGE_CHILDREN, &rusage);
- resp = launch_data_new_opaque(&rusage, sizeof(rusage));
- }
- } else if (!strcmp(cmd, LAUNCH_KEY_STARTJOB)) {
- if ((j = job_find(launch_data_get_string(data))) != NULL) {
- job_dispatch(j, true);
- errno = 0;
- }
- resp = launch_data_new_errno(errno);
- } else if (!strcmp(cmd, LAUNCH_KEY_STOPJOB)) {
- if ((j = job_find(launch_data_get_string(data))) != NULL) {
- job_stop(j);
- errno = 0;
- }
- resp = launch_data_new_errno(errno);
- } else if (!strcmp(cmd, LAUNCH_KEY_REMOVEJOB)) {
- if ((j = job_find(launch_data_get_string(data))) != NULL) {
- job_remove(j);
- errno = 0;
- }
- resp = launch_data_new_errno(errno);
- } else if (!strcmp(cmd, LAUNCH_KEY_SUBMITJOB)) {
- if (launch_data_get_type(data) == LAUNCH_DATA_ARRAY) {
- resp = job_import_bulk(data);
} else {
- if (job_import(data)) {
- errno = 0;
+ if (!strcmp(cmd, LAUNCH_KEY_STARTJOB)) {
+ if ((j = job_find(launch_data_get_string(data))) != NULL) {
+ job_dispatch(j, true);
+ errno = 0;
+ }
+ resp = launch_data_new_errno(errno);
+ } else if (!strcmp(cmd, LAUNCH_KEY_STOPJOB)) {
+ if ((j = job_find(launch_data_get_string(data))) != NULL) {
+ job_stop(j);
+ errno = 0;
+ }
+ resp = launch_data_new_errno(errno);
+ } else if (!strcmp(cmd, LAUNCH_KEY_REMOVEJOB)) {
+ if ((j = job_find(launch_data_get_string(data))) != NULL) {
+ job_remove(j);
+ errno = 0;
+ }
+ resp = launch_data_new_errno(errno);
+ } else if (!strcmp(cmd, LAUNCH_KEY_SUBMITJOB)) {
+ if (launch_data_get_type(data) == LAUNCH_DATA_ARRAY) {
+ resp = job_import_bulk(data);
+ } else {
+ if (job_import(data)) {
+ errno = 0;
+ }
+ resp = launch_data_new_errno(errno);
+ }
+ } else if (!strcmp(cmd, LAUNCH_KEY_UNSETUSERENVIRONMENT)) {
+ unsetenv(launch_data_get_string(data));
+ resp = launch_data_new_errno(0);
+ } else if (!strcmp(cmd, LAUNCH_KEY_SETUSERENVIRONMENT)) {
+ launch_data_dict_iterate(data, set_user_env, NULL);
+ resp = launch_data_new_errno(0);
+ } else if (!strcmp(cmd, LAUNCH_KEY_SETRESOURCELIMITS)) {
+ resp = adjust_rlimits(data);
+ } else if (!strcmp(cmd, LAUNCH_KEY_GETJOB)) {
+ if ((j = job_find(launch_data_get_string(data))) == NULL) {
+ resp = launch_data_new_errno(errno);
+ } else {
+ resp = job_export(j);
+ ipc_revoke_fds(resp);
+ }
+ } else if( !strcmp(cmd, LAUNCH_KEY_SETPRIORITYLIST) ) {
+ resp = launch_data_new_errno(launchd_set_jetsam_priorities(data));
}
- resp = launch_data_new_errno(errno);
}
- } else if (!strcmp(cmd, LAUNCH_KEY_UNSETUSERENVIRONMENT)) {
- unsetenv(launch_data_get_string(data));
- resp = launch_data_new_errno(0);
- } else if (!strcmp(cmd, LAUNCH_KEY_SETUSERENVIRONMENT)) {
- launch_data_dict_iterate(data, set_user_env, NULL);
- resp = launch_data_new_errno(0);
- } else if (!strcmp(cmd, LAUNCH_KEY_SETRESOURCELIMITS)) {
- resp = adjust_rlimits(data);
- } else if (!strcmp(cmd, LAUNCH_KEY_GETJOB)) {
- if ((j = job_find(launch_data_get_string(data))) == NULL) {
- resp = launch_data_new_errno(errno);
- } else {
- resp = job_export(j);
- ipc_revoke_fds(resp);
- }
- } else if( !strcmp(cmd, LAUNCH_KEY_SETPRIORITYLIST) ) {
- resp = launch_data_new_errno(launchd_set_jetsam_priorities(data));
}
rmc->resp = resp;
Modified: trunk/launchd/src/liblaunch.c
===================================================================
--- trunk/launchd/src/liblaunch.c 2009-03-25 21:52:29 UTC (rev 23869)
+++ trunk/launchd/src/liblaunch.c 2009-03-26 07:22:22 UTC (rev 23870)
@@ -147,6 +147,10 @@
};
};
+enum {
+ LAUNCHD_USE_CHECKIN_FD,
+ LAUNCHD_USE_OTHER_FD,
+};
struct _launch {
void *sendbuf;
int *sendfds;
@@ -156,10 +160,9 @@
size_t sendfdcnt;
size_t recvlen;
size_t recvfdcnt;
+ int which;
+ int cifd;
int fd;
-#if __LP64__
- int __pad;
-#endif
};
static launch_data_t launch_data_array_pop_first(launch_data_t where);
@@ -186,7 +189,7 @@
struct sockaddr_un sun;
char *where = getenv(LAUNCHD_SOCKET_ENV);
char *_launchd_fd = getenv(LAUNCHD_TRUSTED_FD_ENV);
- int dfd, lfd = -1;
+ int dfd, lfd = -1, cifd = -1;
name_t spath;
_lc = calloc(1, sizeof(struct _launch_client));
@@ -197,64 +200,78 @@
pthread_mutex_init(&_lc->mtx, NULL);
if (_launchd_fd) {
- lfd = strtol(_launchd_fd, NULL, 10);
- if ((dfd = dup(lfd)) >= 0) {
+ cifd = strtol(_launchd_fd, NULL, 10);
+ if ((dfd = dup(cifd)) >= 0) {
close(dfd);
- _fd(lfd);
+ _fd(cifd);
} else {
- lfd = -1;
+ cifd = -1;
}
unsetenv(LAUNCHD_TRUSTED_FD_ENV);
}
- if (lfd == -1) {
- memset(&sun, 0, sizeof(sun));
- sun.sun_family = AF_UNIX;
-
- /* The rules are as follows.
- * - All users (including root) talk to their per-user launchd's by default.
- * - If we have been invoked under sudo, talk to the system launchd.
- * - If we're the root user and the __USE_SYSTEM_LAUNCHD environment variable is set, then
- * talk to the system launchd.
- */
- if (where && where[0] != '\0') {
- strncpy(sun.sun_path, where, sizeof(sun.sun_path));
- } else {
- if( _vprocmgr_getsocket(spath) == 0 ) {
- if( (getenv("SUDO_COMMAND") || getenv("__USE_SYSTEM_LAUNCHD")) && geteuid() == 0 ) {
- /* Talk to the system launchd. */
- strncpy(sun.sun_path, LAUNCHD_SOCK_PREFIX "/sock", sizeof(sun.sun_path));
- } else {
- /* Talk to our per-user launchd. */
- size_t min_len;
-
- min_len = sizeof(sun.sun_path) < sizeof(spath) ? sizeof(sun.sun_path) : sizeof(spath);
-
- strncpy(sun.sun_path, spath, min_len);
- }
+
+ memset(&sun, 0, sizeof(sun));
+ sun.sun_family = AF_UNIX;
+
+ /* The rules are as follows.
+ * - All users (including root) talk to their per-user launchd's by default.
+ * - If we have been invoked under sudo, talk to the system launchd.
+ * - If we're the root user and the __USE_SYSTEM_LAUNCHD environment variable is set, then
+ * talk to the system launchd.
+ */
+ if (where && where[0] != '\0') {
+ strncpy(sun.sun_path, where, sizeof(sun.sun_path));
+ } else {
+ if( _vprocmgr_getsocket(spath) == 0 ) {
+ if( (getenv("SUDO_COMMAND") || getenv("__USE_SYSTEM_LAUNCHD")) && geteuid() == 0 ) {
+ /* Talk to the system launchd. */
+ strncpy(sun.sun_path, LAUNCHD_SOCK_PREFIX "/sock", sizeof(sun.sun_path));
+ } else {
+ /* Talk to our per-user launchd. */
+ size_t min_len;
+
+ min_len = sizeof(sun.sun_path) < sizeof(spath) ? sizeof(sun.sun_path) : sizeof(spath);
+
+ strncpy(sun.sun_path, spath, min_len);
}
}
+ }
- if ((lfd = _fd(socket(AF_UNIX, SOCK_STREAM, 0))) == -1) {
+ if ((lfd = _fd(socket(AF_UNIX, SOCK_STREAM, 0))) == -1) {
+ goto out_bad;
+ }
+
+ if (-1 == connect(lfd, (struct sockaddr *)&sun, sizeof(sun))) {
+ if( cifd != -1 ) {
+ /* There is NO security enforced by this check. This is just a hint to our
+ * library that we shouldn't error out due to failing to open this socket. If
+ * we inherited a trusted file descriptor, we shouldn't fail. This should be
+ * adequate for clients' expectations.
+ */
+ close(lfd);
+ lfd = -1;
+ } else {
goto out_bad;
}
- if (-1 == connect(lfd, (struct sockaddr *)&sun, sizeof(sun))) {
- goto out_bad;
- }
}
- if (!(_lc->l = launchd_fdopen(lfd))) {
+ if (!(_lc->l = launchd_fdopen(lfd, cifd))) {
goto out_bad;
}
+
if (!(_lc->async_resp = launch_data_alloc(LAUNCH_DATA_ARRAY))) {
goto out_bad;
}
-
+
return;
out_bad:
if (_lc->l)
launchd_close(_lc->l, close);
else if (lfd != -1)
close(lfd);
+ if( cifd != -1 ) {
+ close(cifd);
+ }
if (_lc)
free(_lc);
_lc = NULL;
@@ -318,7 +335,6 @@
return dict->_array_cnt / 2;
}
-
bool
launch_data_dict_insert(launch_data_t dict, launch_data_t what, const char *key)
{
@@ -565,11 +581,11 @@
int
launchd_getfd(launch_t l)
{
- return l->fd;
+ return ( l->which == LAUNCHD_USE_CHECKIN_FD ) ? l->cifd : l->fd;
}
launch_t
-launchd_fdopen(int fd)
+launchd_fdopen(int fd, int cifd)
{
launch_t c;
@@ -578,8 +594,16 @@
return NULL;
c->fd = fd;
+ c->cifd = cifd;
+ if( c->fd == -1 || (c->fd != -1 && c->cifd != -1) ) {
+ c->which = LAUNCHD_USE_CHECKIN_FD;
+ } else if( c->cifd == -1 ) {
+ c->which = LAUNCHD_USE_OTHER_FD;
+ }
+
fcntl(fd, F_SETFL, O_NONBLOCK);
+ fcntl(cifd, F_SETFL, O_NONBLOCK);
if ((c->sendbuf = malloc(0)) == NULL)
goto out_bad;
@@ -621,6 +645,7 @@
if (lh->recvfds)
free(lh->recvfds);
closefunc(lh->fd);
+ closefunc(lh->cifd);
free(lh);
}
@@ -801,6 +826,12 @@
size_t sentctrllen = 0;
int r;
+ int fd2use = launchd_getfd(lh);
+ if( fd2use == -1 ) {
+ errno = EPERM;
+ return -1;
+ }
+
memset(&mh, 0, sizeof(mh));
/* confirm that the next hack works */
@@ -857,7 +888,7 @@
memcpy(CMSG_DATA(cm), lh->sendfds, lh->sendfdcnt * sizeof(int));
}
- if ((r = sendmsg(lh->fd, &mh, 0)) == -1) {
+ if ((r = sendmsg(fd2use, &mh, 0)) == -1) {
return -1;
} else if (r == 0) {
errno = ECONNRESET;
@@ -891,7 +922,6 @@
return 0;
}
-
int
launch_get_fd(void)
{
@@ -987,6 +1017,20 @@
return NULL;
}
+ int fd2use = -1;
+ if( launch_data_get_type(d) == LAUNCH_DATA_STRING && strcmp(launch_data_get_string(d), LAUNCH_KEY_CHECKIN) == 0 ) {
+ _lc->l->which = LAUNCHD_USE_CHECKIN_FD;
+ } else {
+ _lc->l->which = LAUNCHD_USE_OTHER_FD;
+ }
+
+ fd2use = launchd_getfd(_lc->l);
+
+ if( fd2use == -1 ) {
+ errno = EPERM;
+ return NULL;
+ }
+
#if !TARGET_OS_EMBEDDED
uuid_t uuid;
launch_data_t uuid_d = NULL;
@@ -1035,7 +1079,7 @@
goto out;
} while (launchd_msg_send(_lc->l, NULL) == -1);
}
-
+
while (resp == NULL) {
if (d == NULL && launch_data_array_get_count(_lc->async_resp) > 0) {
resp = launch_data_array_pop_first(_lc->async_resp);
@@ -1051,12 +1095,13 @@
fd_set rfds;
FD_ZERO(&rfds);
- FD_SET(_lc->l->fd, &rfds);
+ FD_SET(fd2use, &rfds);
- select(_lc->l->fd + 1, &rfds, NULL, NULL, NULL);
+ select(fd2use + 1, &rfds, NULL, NULL, NULL);
}
}
}
+
out:
#if !TARGET_OS_EMBEDDED
if( !uuid_is_null(uuid) && resp && jobs_that_need_sessions > 0 ) {
@@ -1110,6 +1155,12 @@
struct iovec iov;
int r;
+ int fd2use = launchd_getfd(lh);
+ if( fd2use == -1 ) {
+ errno = EPERM;
+ return -1;
+ }
+
memset(&mh, 0, sizeof(mh));
mh.msg_iov = &iov;
mh.msg_iovlen = 1;
@@ -1121,7 +1172,7 @@
mh.msg_control = cm;
mh.msg_controllen = 4096;
- if ((r = recvmsg(lh->fd, &mh, 0)) == -1)
+ if ((r = recvmsg(fd2use, &mh, 0)) == -1)
return -1;
if (r == 0) {
errno = ECONNRESET;
Modified: trunk/launchd.xcodeproj/project.pbxproj
===================================================================
--- trunk/launchd.xcodeproj/project.pbxproj 2009-03-25 21:52:29 UTC (rev 23869)
+++ trunk/launchd.xcodeproj/project.pbxproj 2009-03-26 07:22:22 UTC (rev 23870)
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 46;
+ objectVersion = 45;
objects = {
/* Begin PBXAggregateTarget section */
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/launchd-changes/attachments/20090326/f8ce31ca/attachment-0001.html>
More information about the launchd-changes
mailing list