Since web frontends may signal an error when requests are malformed or so, let
us double check this and raise errors early. The current user of this is
civetweb frontend; which can potentially return null from `parse_http_headers`
when a HTTP header without a ":" is supplied at which point headers.value is
null which can lead to undefined behaviour later in RGW.
Fixes: http://tracker.ceph.com/issues/23039
Signed-off-by: Abhishek Lekshmanan <abhishek@suse.com>
(cherry picked from commit
7872a831783e17dcc4d0aa70cffc256afb664f7a)
src/rgw/rgw_lib.h:
Added https://github.com/ceph/ceph/pull/19065 to the backport as it is harmless
return 0;
}
-void RGWMongoose::init_env(CephContext *cct)
+int RGWMongoose::init_env(CephContext *cct)
{
env.init(cct);
struct mg_request_info *info = mg_get_request_info(conn);
- if (!info)
- return;
+ if (!info) {
+ return -EINVAL;
+ }
for (int i = 0; i < info->num_headers; i++) {
struct mg_request_info::mg_header *header = &info->http_headers[i];
+ if (header->name == nullptr || header->value == nullptr) {
+ lderr(cct) << "client supplied malformed headers" << dendl;
+ return -EINVAL;
+ }
+
if (strcasecmp(header->name, "content-length") == 0) {
env.set("CONTENT_LENGTH", header->value);
continue;
if (info->is_ssl) {
env.set("SERVER_PORT_SECURE", port_buf);
}
+ return 0;
}
int RGWMongoose::send_status(int status, const char *status_name)
bool explicit_conn_close;
public:
- void init_env(CephContext *cct);
+ int init_env(CephContext *cct) override;
int write_data(const char *buf, int len);
int read_data(char *buf, int len);
#define dout_subsys ceph_subsys_rgw
-void RGWClientIO::init(CephContext *cct) {
- init_env(cct);
+int RGWClientIO::init(CephContext *cct) {
+ int init_error = init_env(cct);
+
+ if (init_error != 0)
+ return init_error;
if (cct->_conf->subsys.should_gather(ceph_subsys_rgw, 20)) {
std::map<string, string, ltstr_nocase>& env_map = env.get_map();
ldout(cct, 20) << iter->first << "=" << iter->second << dendl;
}
}
+
+ return init_error;
}
int RGWStreamIO::print(const char *format, ...)
}
calc_hash_sha256_update_stream(sha256_hash, buf, *actual);
}
-
return 0;
}
protected:
RGWEnv env;
-
- virtual void init_env(CephContext *cct) = 0;
+ virtual int init_env(CephContext *cct) = 0;
public:
virtual ~RGWClientIO() {}
RGWClientIO() : _account(false) {}
- void init(CephContext *cct);
+ /* Initialize the BasicClient and inject CephContext. */
+ int init(CephContext *cct);
RGWEnv& get_env() { return env; }
bool account() { return _account; }
FCGX_FFlush(fcgx->out);
}
-void RGWFCGX::init_env(CephContext *cct)
+int RGWFCGX::init_env(CephContext* const cct)
{
env.init(cct, (char **)fcgx->envp);
+ return 0;
}
int RGWFCGX::send_status(int status, const char *status_name)
int status_num;
protected:
- void init_env(CephContext *cct);
+ int init_env(CephContext *cct) override;
int write_data(const char *buf, int len);
int read_data(char *buf, int len);
RGWLibIO(const RGWUserInfo &_user_info)
: user_info(_user_info) {}
- virtual void init_env(CephContext *cct) {}
+
+ int init_env(CephContext *cct) override {
+ env.init(cct);
+ return 0;
+ }
const RGWUserInfo& get_user() {
return user_info;
return 0;
}
-void RGWLoadGenIO::init_env(CephContext *cct)
+int RGWLoadGenIO::init_env(CephContext *cct)
{
env.init(cct);
char port_buf[16];
snprintf(port_buf, sizeof(port_buf), "%d", req->port);
env.set("SERVER_PORT", port_buf);
+ return 0;
}
int RGWLoadGenIO::send_status(int status, const char *status_name)
uint64_t left_to_read;
RGWLoadGenRequestEnv *req;
public:
- void init_env(CephContext *cct);
+ int init_env(CephContext *cct) override;
int write_data(const char *buf, int len);
int read_data(char *buf, int len);
int process_request(RGWRados* store, RGWREST* rest, RGWRequest* req,
RGWStreamIO* client_io, OpsLogSocket* olog)
{
- int ret = 0;
-
- client_io->init(g_ceph_context);
+ int ret = client_io->init(g_ceph_context);
req->log_init();
RGWObjectCtx rados_ctx(store, s);
s->obj_ctx = &rados_ctx;
+ if (ret < 0) {
+ s->cio = client_io;
+ abort_early(s, nullptr, ret, nullptr);
+ return ret;
+ }
+
s->req_id = store->unique_id(req->id);
s->trans_id = store->unique_trans_id(req->id);
s->host_id = store->host_id;
req->log_format(s, "initializing for trans_id = %s", s->trans_id.c_str());
- RGWOp* op = NULL;
+ RGWOp* op = nullptr;
int init_error = 0;
bool should_log = false;
RGWRESTMgr *mgr;
RGWHandler_REST *handler = rest->get_handler(store, s, client_io, &mgr,
&init_error);
if (init_error != 0) {
- abort_early(s, NULL, init_error, NULL);
+ abort_early(s, nullptr, init_error, nullptr);
goto done;
}
dout(10) << "handler=" << typeid(*handler).name() << dendl;