fix(controller): reject submissions to closed or unknown queues (bug-1960)
Cause: handle_jobsubmit() never looked at the target queue, so a submission that bypassed the apiserver's check (libxce, harness xce_test, or a REST submit without a queue name) was accepted into a closed queue, an unknown queue, or the reserved lost_and_found queue. Fix: jobsubmit_check_queue() reads the queue's in-memory state under the qmgr/queue read locks. handle_jobsubmit() calls it after the field checks and before the in-flight jobid registry and any WAL append, for single jobs and job arrays. It replies -E_XCE_QUEUE_CLOSED (new code, "queue is closed") for a closed queue and -E_XCE_BAD_QUEUE for an unknown or reserved one. Apply/replay (restore_job) is unchanged, so committed submit facts for a now-closed queue still apply. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
387cc99486
commit
b239db5fa3
7 changed files with 272 additions and 1 deletions
|
|
@ -8,6 +8,7 @@
|
|||
#include <time.h>
|
||||
|
||||
#include "cluster.h"
|
||||
#include "config_repl.h" /* XCE_LOST_AND_FOUND_NAME -- bug-1960 */
|
||||
#include "controller.capnp.h"
|
||||
#include "jobj.h"
|
||||
#include "persist.h"
|
||||
|
|
@ -2608,6 +2609,45 @@ jobsubmit_class_t jobsubmit_classify(uint64_t first_jobid, uint64_t size)
|
|||
return JOBSUBMIT_OK;
|
||||
}
|
||||
|
||||
/* bug-1960: queue admission for a NEW client submission. Returns 0 when
|
||||
* `queue` takes new jobs; -E_XCE_BAD_QUEUE when the controller has no such
|
||||
* queue or it is the reserved recovery queue (jobs reach lost_and_found only
|
||||
* through WAL replay, never by submission; the apiserver rejects it too);
|
||||
* -E_XCE_QUEUE_CLOSED when it is closed (LSF semantics: a closed queue takes
|
||||
* no new submissions, its pending jobs still dispatch -- bug-1938).
|
||||
*
|
||||
* Reads in-memory queue state only, under the qmgr and queue read locks
|
||||
* (the queue_ctrl()/get_queue_exec() lookup pattern), no blocking I/O. It
|
||||
* belongs to handle_jobsubmit() alone: apply/replay of an already-committed
|
||||
* WAL_JOB_SUBMIT fact (restore_job) must not consult it, so a job accepted
|
||||
* before its queue was closed still applies on a standby or after restart. */
|
||||
static int jobsubmit_check_queue(cluster_t* c, const char* queue)
|
||||
{
|
||||
queue_t* q = NULL;
|
||||
uint32_t status;
|
||||
|
||||
if (strcmp(queue, XCE_LOST_AND_FOUND_NAME) == 0)
|
||||
return -E_XCE_BAD_QUEUE;
|
||||
|
||||
lock(c->qmgr, RTTI_LOCK_READ);
|
||||
key_find(c->qmgr, (void*)queue, (void**)&q);
|
||||
if (q != NULL) {
|
||||
reference(q);
|
||||
}
|
||||
unlock(c->qmgr);
|
||||
|
||||
if (q == NULL)
|
||||
return -E_XCE_BAD_QUEUE;
|
||||
|
||||
lock(q, RTTI_LOCK_READ);
|
||||
status = q->queue.status;
|
||||
unlock(q);
|
||||
|
||||
dereference(q);
|
||||
|
||||
return (status & QUEUE_STAT_CLOSED) ? -E_XCE_QUEUE_CLOSED : 0;
|
||||
}
|
||||
|
||||
int handle_jobsubmit(cluster_t* c, endpoint_t* ep, xce_request_t* request)
|
||||
{
|
||||
uint64_t jobid;
|
||||
|
|
@ -2664,6 +2704,29 @@ int handle_jobsubmit(cluster_t* c, endpoint_t* ep, xce_request_t* request)
|
|||
return -errno;
|
||||
}
|
||||
|
||||
/* bug-1960: reject a submission to a closed, unknown or reserved queue
|
||||
* before the in-flight registry claims its jobid range and before any
|
||||
* WAL fact is appended -- nothing is stored, the client gets the
|
||||
* queue's status alone. Covers the single-job and the array path
|
||||
* (handle_jobsubmit_array diverges below). */
|
||||
rc = jobsubmit_check_queue(c, submit->submit->queue);
|
||||
if (rc < 0) {
|
||||
char idstr[64];
|
||||
|
||||
fmt_jobid(idstr, sizeof(idstr), submit->jobid);
|
||||
ERROR("jobsubmit: rejected submission %s (%lu elements) to queue "
|
||||
"'%s': %s",
|
||||
idstr, (unsigned long)submit->array_size, submit->submit->queue,
|
||||
(rc == -E_XCE_QUEUE_CLOSED)
|
||||
? "queue is closed"
|
||||
: "no such queue or not a submission queue");
|
||||
reply.status = rc;
|
||||
reply.data_which = RequestReply_data_nodata;
|
||||
|
||||
xce_reply(ep, c->myhost, &reply);
|
||||
return rc;
|
||||
}
|
||||
|
||||
xce_run_hooks(&(c->hooksys), XCE_CONTROLLER_HOOK_JOB, HOOK_BEFORE_EVENT,
|
||||
HOOK_DETAIL_JOB_NEW, c, submit);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue