corrupt(conn, "Could not delete '%s'", node->name);
return;
}
- domain_entry_dec(conn);
+ domain_entry_dec(conn, node);
}
/* Must not be / */
node->children = node->data = NULL;
node->childlen = node->datalen = 0;
node->parent = parent;
- domain_entry_inc(conn);
+ domain_entry_inc(conn, node);
return node;
}
* something goes wrong. */
for (i = node; i; i = i->parent) {
if (!write_node(conn, i)) {
- domain_entry_dec(conn);
+ domain_entry_dec(conn, i);
return NULL;
}
talloc_set_destructor(i, destroy_node);
static void do_set_perms(struct connection *conn, struct buffered_data *in)
{
unsigned int num;
+ struct xs_permissions *perms;
char *name, *permstr;
struct node *node;
return;
}
- node->perms = talloc_array(node, struct xs_permissions, num);
- node->num_perms = num;
- if (!xs_strings_to_perms(node->perms, num, permstr)) {
+ perms = talloc_array(node, struct xs_permissions, num);
+ if (!xs_strings_to_perms(perms, num, permstr)) {
send_error(conn, errno);
return;
}
+
+ /* Unprivileged domains may not change the owner. */
+ if (domain_is_unprivileged(conn) &&
+ perms[0].id != node->perms[0].id) {
+ send_error(conn, EPERM);
+ return;
+ }
+
+ domain_entry_dec(conn, node);
+ node->perms = perms;
+ node->num_perms = num;
+ domain_entry_inc(conn, node);
+
if (!write_node(conn, node)) {
send_error(conn, errno);
return;
return xce_handle;
}
-void domain_entry_inc(struct connection *conn)
+void domain_entry_inc(struct connection *conn, struct node *node)
{
- if (!conn || !conn->domain)
+ struct domain *d;
+
+ if (!conn)
return;
- conn->domain->nbentry++;
+
+ if (node->perms && node->perms[0].id != conn->id) {
+ d = find_domain_by_domid(node->perms[0].id);
+ if (d)
+ d->nbentry++;
+ }
+ else if (conn->domain) {
+ conn->domain->nbentry++;
+ }
}
-void domain_entry_dec(struct connection *conn)
+void domain_entry_dec(struct connection *conn, struct node *node)
{
- if (!conn || !conn->domain)
+ struct domain *d;
+
+ if (!conn)
return;
- if (conn->domain->nbentry)
+
+ if (node->perms && node->perms[0].id != conn->id) {
+ d = find_domain_by_domid(node->perms[0].id);
+ if (d && d->nbentry)
+ d->nbentry--;
+ } else if (conn->domain && conn->domain->nbentry)
conn->domain->nbentry--;
}
bool domain_is_unprivileged(struct connection *conn);
/* Quota manipulation */
-void domain_entry_inc(struct connection *conn);
-void domain_entry_dec(struct connection *conn);
+void domain_entry_inc(struct connection *conn, struct node *);
+void domain_entry_dec(struct connection *conn, struct node *);
int domain_entry(struct connection *conn);
void domain_watch_inc(struct connection *conn);
void domain_watch_dec(struct connection *conn);