/**
* A random number used to "authenticate" the connection.
*
- * para_server picks this number by random before forking the afs process. The
- * command handlers write this number together with the id of the shared memory
- * area containing the query. This way, a malicious local user has to know this
- * number to be able to cause the afs process to crash by sending fake queries.
+ * para_server picks this number by random before it forks the afs process. The
+ * command handlers know this number as well and write it to the afs socket,
+ * together with the id of the shared memory area which contains the payload of
+ * the afs command. A local process has to know this number to abuse the afs
+ * service provided by the local socket.
*/
extern uint32_t afs_socket_cookie;
{
struct msghdr msg = {.msg_iov = NULL};
struct cmsghdr *cmsg;
- char control[255];
+ char control[255] __a_aligned(8);
int ret;
struct iovec iov;
}
/* Never fails if arg == NULL */
-static int activate_mood_or_playlist(char *arg, int *num_admissible)
+static int activate_mood_or_playlist(const char *arg, int *num_admissible)
{
enum play_mode mode;
int ret;
- PARA_INFO_LOG("new playlist: %s\n", arg);
if (!arg) {
ret = change_current_mood(NULL); /* always successful */
mode = PLAY_MODE_MOOD;
}
}
-void flush_and_free_pb(struct para_buffer *pb)
+static void flush_and_free_pb(struct para_buffer *pb)
{
int ret;
struct afs_max_size_handler_data *amshd = pb->private_data;
static int com_select_callback(struct afs_callback_arg *aca)
{
- struct para_buffer pb = {
- .max_size = shm_get_shmmax(),
- .private_data = &(struct afs_max_size_handler_data) {
- .fd = aca->fd,
- .band = SBD_OUTPUT
- },
- .max_size_handler = afs_max_size_handler,
- };
- char *arg = aca->query.data;
+ const char *arg = aca->query.data;
int num_admissible, ret;
ret = clear_score_table();
if (ret < 0) {
- para_printf(&pb, "could not clear score table: %s\n",
+ para_printf(&aca->pbout, "could not clear score table: %s\n",
para_strerror(-ret));
return ret;
}
ret = activate_mood_or_playlist(arg, &num_admissible);
if (ret >= 0)
goto out;
- para_printf(&pb, "could not activate %s: %s\n"
- "switching back to %s\n",
- arg, para_strerror(-ret), current_mop? current_mop : "dummy");
/* ignore subsequent errors (but log them) */
- ret = activate_mood_or_playlist(current_mop, &num_admissible);
- if (ret >= 0)
- goto out;
- para_printf(&pb, "could not activate %s: %s\nswitching to dummy\n",
- current_mop, para_strerror(-ret));
+ para_printf(&aca->pbout, "could not activate %s\n", arg);
+ if (current_mop) {
+ int ret2;
+ para_printf(&aca->pbout, "switching back to %s\n", current_mop);
+ ret2 = activate_mood_or_playlist(current_mop, &num_admissible);
+ if (ret2 >= 0)
+ goto out;
+ para_printf(&aca->pbout, "could not reactivate %s: %s\n",
+ current_mop, para_strerror(-ret2));
+ }
+ para_printf(&aca->pbout, "activating dummy mood\n");
activate_mood_or_playlist(NULL, &num_admissible);
out:
- para_printf(&pb, "activated %s (%d admissible files)\n",
+ para_printf(&aca->pbout, "activated %s (%d admissible files)\n",
current_mop? current_mop : "dummy mood", num_admissible);
- flush_and_free_pb(&pb);
return ret;
}
ret = create_local_socket(socket_name, 0);
if (ret < 0) {
ret = create_local_socket(socket_name,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IWOTH);
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IROTH);
if (ret < 0) {
PARA_EMERG_LOG("%s: %s\n", para_strerror(-ret),
socket_name);
get_database_dir();
ret = para_mkdir(database_dir, 0777);
- if (ret >= 0 || is_errno(-ret, EEXIST))
+ if (ret >= 0 || ret == -ERRNO_TO_PARA_ERROR(EEXIST))
return 1;
return ret;
}
int i, ret;
get_database_dir();
- PARA_NOTICE_LOG("opening %u osl tables in %s\n", NUM_AFS_TABLES,
+ PARA_NOTICE_LOG("opening %d osl tables in %s\n", NUM_AFS_TABLES,
database_dir);
for (i = 0; i < NUM_AFS_TABLES; i++) {
ret = afs_tables[i].open(database_dir);
cq = query_shm;
aca.query.data = (char *)query_shm + sizeof(*cq);
aca.query.size = cq->query_size;
+ aca.pbout.max_size = shm_get_shmmax();
+ aca.pbout.max_size_handler = afs_max_size_handler;
+ aca.pbout.private_data = &(struct afs_max_size_handler_data) {
+ .fd = fd,
+ .band = SBD_OUTPUT
+ };
ret = cq->handler(&aca);
ret2 = shm_detach(query_shm);
if (ret2 < 0) {
else
ret = ret2;
}
+ flush_and_free_pb(&aca.pbout);
if (ret < 0) {
ret2 = pass_buffer_as_shm(fd, SBD_AFS_CB_FAILURE,
(const char *)&ret, sizeof(ret));
register_command_task(cookie, &s);
s.default_timeout.tv_sec = 0;
s.default_timeout.tv_usec = 999 * 1000;
+ ret = write(socket_fd, "\0", 1);
+ if (ret != 1) {
+ if (ret == 0)
+ errno = EINVAL;
+ ret = -ERRNO_TO_PARA_ERROR(errno);
+ goto out_close;
+ }
ret = schedule(&s);
sched_shutdown(&s);
out_close:
{
uint32_t table_mask = *(uint32_t *)aca->query.data;
int i, ret;
- struct para_buffer pb = {
- .max_size = shm_get_shmmax(),
- .private_data = &(struct afs_max_size_handler_data) {
- .fd = aca->fd,
- .band = SBD_OUTPUT
- }
- };
close_afs_tables();
for (i = 0; i < NUM_AFS_TABLES; i++) {
continue;
ret = t->create(database_dir);
if (ret < 0) {
- para_printf(&pb, "cannot create table %s\n", t->name);
+ para_printf(&aca->pbout, "cannot create table %s\n",
+ t->name);
goto out;
}
- para_printf(&pb, "successfully created %s table\n", t->name);
+ para_printf(&aca->pbout, "successfully created %s table\n",
+ t->name);
}
ret = open_afs_tables();
if (ret < 0)
- para_printf(&pb, "cannot open afs tables\n");
+ para_printf(&aca->pbout, "cannot open afs tables\n");
out:
- flush_and_free_pb(&pb);
return ret;
}
continue;
ret = t->event_handler(event, pb, data);
if (ret < 0) {
- PARA_CRIT_LOG("table %s, event %d: %s\n", t->name,
+ PARA_CRIT_LOG("table %s, event %u: %s\n", t->name,
event, para_strerror(-ret));
return ret;
}